mirror of
https://github.com/vincentbernat/i3wm-configuration.git
synced 2025-06-21 01:25:42 +02:00
Initial commit.
This commit is contained in:
commit
c130561cb7
17 changed files with 1029 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*~
|
||||
/wallpapers
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "themes/nice-and-clean-theme"]
|
||||
path = themes/nice-and-clean-theme
|
||||
url = https://github.com/waf/nice-and-clean-theme/
|
89
bin/build-wallpaper
Executable file
89
bin/build-wallpaper
Executable file
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Build a multi screen wallpaper
|
||||
|
||||
# First argument is the directory where the wallpapers can be
|
||||
# found. We use xinerama to know the dimension of each screen.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import random
|
||||
import string
|
||||
import subprocess
|
||||
import optparse
|
||||
|
||||
import xcb
|
||||
import xcb.xproto
|
||||
import xcb.xinerama
|
||||
|
||||
import Image
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option("-d", "--directory", dest="directory", default=".",
|
||||
help="search for images in DIRECTORY", metavar="DIRECTORY")
|
||||
parser.add_option("-t", "--target", dest="target", default="background.jpg",
|
||||
help="write background to FILE", metavar="FILE")
|
||||
parser.add_option("-c", "--crop", dest="crop", action="store_true",
|
||||
help="crop image instead of centering them")
|
||||
options, args = parser.parse_args()
|
||||
|
||||
assert not args, "No additional arguments are accepted"
|
||||
|
||||
background = None
|
||||
|
||||
# Get display size
|
||||
display = xcb.connect()
|
||||
root = display.get_setup().roots[0]
|
||||
background = Image.new('RGB', (root.width_in_pixels, root.height_in_pixels))
|
||||
|
||||
# Query xinerama (not randr since the query is longer)
|
||||
try:
|
||||
xinerama = display(xcb.xinerama.key)
|
||||
except xcb.ExtensionException:
|
||||
xinerama = None
|
||||
if not xinerama or not xinerama.IsActive().reply().state:
|
||||
screens = [(background.size[0], background.size[1], 0, 0)]
|
||||
else:
|
||||
screens = [(screen.width, screen.height, screen.x_org, screen.y_org)
|
||||
for screen in xinerama.QueryScreens().reply().screen_info]
|
||||
screens.sort(key=lambda screen: -screen[0]*screen[1])
|
||||
|
||||
# Get as many random image as we have screens
|
||||
images = []
|
||||
for root, _, files in os.walk(os.path.join(options.directory)):
|
||||
for i in files:
|
||||
if string.lower(os.path.splitext(i)[1]) in ('.jpg',
|
||||
'.jpeg',
|
||||
'.png'):
|
||||
images.append(os.path.join(root, i))
|
||||
images = random.sample(images,
|
||||
len(screens) + \
|
||||
random.randint(0, 3)) # Randomly favor larger images
|
||||
images = [Image.open(os.path.join(options.directory,
|
||||
image)) for image in images]
|
||||
images.sort(key=lambda image: -image.size[0]*image.size[1])
|
||||
|
||||
for index in range(len(screens)):
|
||||
x, y, offsetx, offsety = screens[index]
|
||||
image = images[index]
|
||||
|
||||
# Find the right size for the screen
|
||||
imx, imy = x, image.size[1]*x/image.size[0]
|
||||
if (options.crop and imy < y) or (not options.crop and imy > y):
|
||||
imx, imy = image.size[0]*y/image.size[1], y
|
||||
image = image.resize((imx, imy), Image.CUBIC)
|
||||
if options.crop:
|
||||
image = image.crop(((imx-x)/2, (imy-y)/2,
|
||||
imx-(imx-x)/2, imy-(imy-y)/2))
|
||||
|
||||
# Include it
|
||||
if options.crop:
|
||||
background.paste(image, (offsetx, offsety))
|
||||
else:
|
||||
background.paste(image, ((x-imx)/2 + offsetx,
|
||||
(y-imy)/2 + offsety))
|
||||
|
||||
# Save
|
||||
assert background, "Don't know the size of the display area"
|
||||
background.save(options.target)
|
50
rc.lua
Normal file
50
rc.lua
Normal file
|
@ -0,0 +1,50 @@
|
|||
require("awful")
|
||||
require("awful.autofocus")
|
||||
require("awful.rules")
|
||||
require("beautiful")
|
||||
require("naughty")
|
||||
|
||||
-- Simple function to load additional LUA files from rc/.
|
||||
function loadrc(name)
|
||||
local success
|
||||
local result
|
||||
local path = awful.util.getdir("config") .. "/rc/" .. name .. ".lua"
|
||||
success, result = pcall(function() return dofile(path) end)
|
||||
if not success then
|
||||
return print("E: error loading RC file '" .. name .. "': " .. result)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
-- Error handling
|
||||
loadrc("errors")
|
||||
|
||||
-- Global configuration
|
||||
modkey = "Mod4"
|
||||
config = {}
|
||||
config.terminal = table.concat({"urxvtcd",
|
||||
"++iso14755 +sb -si -sw -j -fn fixed -sl 2000",
|
||||
"-fade 40 -sh 30 -bc -tint white -fg white -depth 32",
|
||||
"--color4 RoyalBlue --color12 RoyalBlue",
|
||||
"-bg rgba:0000/0000/0000/bbbb -fadecolor rgba:0000/0000/0000/6666"},
|
||||
" ")
|
||||
config.layouts = {
|
||||
awful.layout.suit.tile,
|
||||
awful.layout.suit.magnifier,
|
||||
awful.layout.suit.floating,
|
||||
}
|
||||
config.hostname = awful.util.pread('uname -n'):gsub('\n', '')
|
||||
|
||||
-- Remaining modules
|
||||
loadrc("theme")
|
||||
loadrc("start")
|
||||
loadrc("bindings")
|
||||
loadrc("wallpaper")
|
||||
loadrc("tags")
|
||||
loadrc("widgets")
|
||||
loadrc("xlock")
|
||||
loadrc("signals")
|
||||
loadrc("rules")
|
||||
|
||||
root.keys(config.keys.global)
|
||||
startapps()
|
74
rc/bindings.lua
Normal file
74
rc/bindings.lua
Normal file
|
@ -0,0 +1,74 @@
|
|||
config.keys = {}
|
||||
config.mouse = {}
|
||||
|
||||
config.keys.global = awful.util.table.join(
|
||||
-- Tag navigation
|
||||
awful.key({ modkey, }, "Left", awful.tag.viewprev ),
|
||||
awful.key({ modkey, }, "Right", awful.tag.viewnext ),
|
||||
awful.key({ modkey, }, "Escape", awful.tag.history.restore),
|
||||
|
||||
-- Focus
|
||||
awful.key({ modkey, }, "j",
|
||||
function ()
|
||||
awful.client.focus.byidx( 1)
|
||||
if client.focus then client.focus:raise() end
|
||||
end),
|
||||
awful.key({ modkey, }, "k",
|
||||
function ()
|
||||
awful.client.focus.byidx(-1)
|
||||
if client.focus then client.focus:raise() end
|
||||
end),
|
||||
awful.key({ modkey, }, "u", awful.client.urgent.jumpto),
|
||||
|
||||
-- Layout manipulation
|
||||
awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end),
|
||||
awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end),
|
||||
awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1) end),
|
||||
awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end),
|
||||
awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1) end),
|
||||
awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end),
|
||||
awful.key({ modkey, }, "space", function () awful.layout.inc(config.layouts, 1) end),
|
||||
awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(config.layouts, -1) end),
|
||||
awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end),
|
||||
awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end),
|
||||
awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end),
|
||||
awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end),
|
||||
awful.key({ modkey, }, "Tab",
|
||||
function ()
|
||||
awful.client.focus.history.previous()
|
||||
if client.focus then
|
||||
client.focus:raise()
|
||||
end
|
||||
end),
|
||||
|
||||
-- Spawn a terminal
|
||||
awful.key({ modkey, }, "Return", function () awful.util.spawn(config.terminal) end),
|
||||
|
||||
-- Restart awesome
|
||||
awful.key({ modkey, "Control" }, "r", awesome.restart)
|
||||
)
|
||||
|
||||
config.keys.client = awful.util.table.join(
|
||||
awful.key({ modkey, }, "f", function (c) c.fullscreen = not c.fullscreen end),
|
||||
awful.key({ modkey, }, "x", function (c) c:kill() end),
|
||||
awful.key({ modkey, }, "o", awful.client.movetoscreen ),
|
||||
awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ),
|
||||
awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end),
|
||||
awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end),
|
||||
awful.key({ modkey, }, "m",
|
||||
function (c)
|
||||
c.maximized_horizontal = not c.maximized_horizontal
|
||||
c.maximized_vertical = not c.maximized_vertical
|
||||
end),
|
||||
awful.key({ modkey, }, "i",
|
||||
function (c)
|
||||
-- The client currently has the input focus, so it cannot be
|
||||
-- minimized, since minimized clients can't have the focus.
|
||||
c.minimized = true
|
||||
end)
|
||||
)
|
||||
|
||||
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))
|
31
rc/errors.lua
Normal file
31
rc/errors.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
require("awesome")
|
||||
require("naughty")
|
||||
|
||||
-- Check if awesome encountered an error during startup and fell back to
|
||||
-- another config (This code will only ever execute for the fallback config)
|
||||
if awesome.startup_errors then
|
||||
naughty.notify({ preset = naughty.config.presets.critical,
|
||||
title = "Oops, there were errors during startup!",
|
||||
text = awesome.startup_errors })
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
function dbg(vars)
|
||||
local text = ""
|
||||
for i=1, #vars do text = text .. vars[i] .. " | " end
|
||||
naughty.notify({ text = text, timeout = 0 })
|
||||
end
|
21
rc/rules.lua
Normal file
21
rc/rules.lua
Normal file
|
@ -0,0 +1,21 @@
|
|||
awful.rules.rules = {
|
||||
-- All clients will match this rule.
|
||||
{ rule = { },
|
||||
properties = { border_width = beautiful.border_width,
|
||||
border_color = beautiful.border_normal,
|
||||
focus = true,
|
||||
keys = config.keys.client,
|
||||
buttons = config.mouse.client }},
|
||||
{ rule = { class = "Emacs" },
|
||||
properties = { tag = config.tags.emacs }},
|
||||
{ rule = { name = "Iceweasel" },
|
||||
properties = { tag = config.tags.www }},
|
||||
{ rule = { name = "Firefox" },
|
||||
properties = { tag = config.tags.www }},
|
||||
{ rule = { name = "Chromium" },
|
||||
properties = { tag = config.tags.www }},
|
||||
{ rule = { class = "Pidgin" },
|
||||
properties = { tag = config.tags.im }},
|
||||
{ rule = { class = "URxvt" },
|
||||
properties = { }, callback = awful.client.setslave },
|
||||
}
|
356
rc/sharetags.lua
Normal file
356
rc/sharetags.lua
Normal file
|
@ -0,0 +1,356 @@
|
|||
-- functions to share tags on multiple screens
|
||||
|
||||
--{{{ Grab environment we need
|
||||
local capi = { widget = widget,
|
||||
screen = screen,
|
||||
image = image,
|
||||
client = client,
|
||||
button = button }
|
||||
local setmetatable = setmetatable
|
||||
local math = math
|
||||
local type = type
|
||||
local pcall = pcall
|
||||
local util = require("awful.util")
|
||||
local tag = require("awful.tag")
|
||||
local beautiful = require("beautiful")
|
||||
local layout = require("awful.widget.layout")
|
||||
|
||||
local awful = require("awful")
|
||||
local mouse = mouse
|
||||
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
--}}}
|
||||
|
||||
module("sharetags")
|
||||
|
||||
--{{{ Private structures
|
||||
tagwidgets = setmetatable({}, { __mode = 'k' })
|
||||
local cachedtags = {}
|
||||
label = {}
|
||||
--}}}
|
||||
|
||||
--{{{ Functions
|
||||
|
||||
--{{{ create_tags: create a table of tags and bind them to screens
|
||||
-- @param names : list to label the tags
|
||||
-- @param layouts : list of layouts for the tags
|
||||
-- @return table of tag objects
|
||||
function create_tags(names, layouts)
|
||||
local tags = {}
|
||||
local count = #names
|
||||
if capi.screen.count() >= #names then
|
||||
count = capi.screen.count() + 1
|
||||
end
|
||||
for tagnumber = 1, count do
|
||||
tags[tagnumber] = awful.tag.add(names[tagnumber], {})
|
||||
tag.setproperty(tags[tagnumber], "number", tagnumber)
|
||||
-- Add tags to screen one by one
|
||||
tags[tagnumber].screen = 1
|
||||
awful.layout.set(layouts[tagnumber], tags[tagnumber])
|
||||
end
|
||||
for s = 1, capi.screen.count() do
|
||||
-- I'm sure you want to see at least one tag.
|
||||
tags[s].screen = s
|
||||
tags[s].selected = true
|
||||
end
|
||||
cachedtags = tags
|
||||
return tags
|
||||
end
|
||||
--}}}
|
||||
|
||||
--{{{ tag_move: move a tag to a screen
|
||||
-- @param t : the tag object to move
|
||||
-- @param scr : the screen object to move to
|
||||
function tag_move(t, scr)
|
||||
local ts = t or awful.tag.selected()
|
||||
local screen_target = scr or awful.util.cycle(capi.screen.count(), ts.screen + 1)
|
||||
|
||||
if ts.screen and screen_target ~= ts.screen then
|
||||
-- switch for tag
|
||||
ts.screen = screen_target
|
||||
-- switch for all clients on tag
|
||||
if #ts:clients() > 0 then
|
||||
for _ , c in ipairs(ts:clients()) do
|
||||
if not c.sticky then
|
||||
c.screen = screen_target
|
||||
c:tags( {ts} )
|
||||
else
|
||||
awful.client.toggletag(ts,c)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--}}}
|
||||
|
||||
--{{{ tag_to_screen: move a tag to a screen if its not already there
|
||||
-- @param t : the tag object to move
|
||||
-- @param scr : the screen object to move to
|
||||
function tag_to_screen(t, scr)
|
||||
local ts = t or awful.tag.selected()
|
||||
local screen_origin = ts.screen
|
||||
local screen_target = scr or awful.util.cycle(capi.screen.count(), ts.screen + 1)
|
||||
|
||||
awful.tag.history.restore(ts.screen,1)
|
||||
-- move the tag only if we are on a different screen
|
||||
if screen_origin ~= screen_target then
|
||||
tag_move(ts, screen_target)
|
||||
end
|
||||
|
||||
awful.tag.viewonly(ts)
|
||||
mouse.screen = ts.screen
|
||||
if #ts:clients() > 0 then
|
||||
local c = ts:clients()[1]
|
||||
capi.client.focus = c
|
||||
end
|
||||
end
|
||||
--}}}
|
||||
|
||||
--{{{ Return labels for a taglist widget with all tag from screen.
|
||||
-- It returns the tag name and set a special
|
||||
-- foreground and background color for selected tags.
|
||||
-- @param t The tag.
|
||||
-- @param args The arguments table.
|
||||
-- bg_focus The background color for selected tag.
|
||||
-- fg_focus The foreground color for selected tag.
|
||||
-- bg_urgent The background color for urgent tags.
|
||||
-- fg_urgent The foreground color for urgent tags.
|
||||
-- squares_sel Optional: a user provided image for selected squares.
|
||||
-- squares_unsel Optional: a user provided image for unselected squares.
|
||||
-- squares_resize Optional: true or false to resize squares.
|
||||
-- @return A string to print, a background color, a background image and a
|
||||
-- background resize value.
|
||||
function label.all(t, args)
|
||||
if not args then args = {} end
|
||||
local theme = beautiful.get()
|
||||
local fg_focus = args.fg_focus or theme.taglist_fg_focus or theme.fg_focus
|
||||
local bg_focus = args.bg_focus or theme.taglist_bg_focus or theme.bg_focus
|
||||
local fg_urgent = args.fg_urgent or theme.taglist_fg_urgent or theme.fg_urgent
|
||||
local bg_urgent = args.bg_urgent or theme.taglist_bg_urgent or theme.bg_urgent
|
||||
local bg_occupied = args.bg_occupied or theme.taglist_bg_occupied
|
||||
local fg_occupied = args.fg_occupied or theme.taglist_fg_occupied
|
||||
local taglist_squares_sel = args.squares_sel or theme.taglist_squares_sel
|
||||
local taglist_squares_unsel = args.squares_unsel or theme.taglist_squares_unsel
|
||||
local taglist_squares_resize = theme.taglist_squares_resize or args.squares_resize or "true"
|
||||
local font = args.font or theme.taglist_font or theme.font or ""
|
||||
local text = "<span font_desc='"..font.."'>"
|
||||
local sel = capi.client.focus
|
||||
local bg_color = nil
|
||||
local fg_color = nil
|
||||
local bg_image
|
||||
local icon
|
||||
local bg_resize = false
|
||||
local is_selected = false
|
||||
if not args.screen then
|
||||
args.screen = t.screen
|
||||
end
|
||||
if t.selected and t.screen == args.screen then
|
||||
bg_color = bg_focus
|
||||
fg_color = fg_focus
|
||||
end
|
||||
if sel and sel.type ~= "desktop" then
|
||||
if taglist_squares_sel then
|
||||
-- Check that the selected clients is tagged with 't'.
|
||||
local seltags = sel:tags()
|
||||
for _, v in ipairs(seltags) do
|
||||
if v == t then
|
||||
bg_image = capi.image(taglist_squares_sel)
|
||||
bg_resize = taglist_squares_resize == "true"
|
||||
is_selected = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not is_selected then
|
||||
local cls = t:clients()
|
||||
if #cls > 0 then
|
||||
if taglist_squares_unsel then
|
||||
bg_image = capi.image(taglist_squares_unsel)
|
||||
bg_resize = taglist_squares_resize == "true"
|
||||
end
|
||||
if bg_occupied then bg_color = bg_occupied end
|
||||
if fg_occupied then fg_color = fg_occupied end
|
||||
end
|
||||
for k, c in pairs(cls) do
|
||||
if c.urgent then
|
||||
if bg_urgent then bg_color = bg_urgent end
|
||||
if fg_urgent then fg_color = fg_urgent end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if not tag.getproperty(t, "icon_only") then
|
||||
if fg_color then
|
||||
text = text .. "<span color='"..util.color_strip_alpha(fg_color).."'>"
|
||||
text = " " .. text.. (util.escape(t.name) or "") .." </span>"
|
||||
else
|
||||
text = text .. " " .. (util.escape(t.name) or "") .. " "
|
||||
end
|
||||
end
|
||||
text = text .. "</span>"
|
||||
if tag.geticon(t) and type(tag.geticon(t)) == "image" then
|
||||
icon = tag.geticon(t)
|
||||
elseif tag.geticon(t) then
|
||||
icon = capi.image(tag.geticon(t))
|
||||
end
|
||||
|
||||
return text, bg_color, bg_image, icon
|
||||
end
|
||||
--}}}
|
||||
|
||||
--{{{ list_update: update a list of widgets
|
||||
-- @param screen : the screen to draw the taglist for
|
||||
-- @param w : the widget container
|
||||
-- @param label : label function to use
|
||||
-- @param buttons : a table with button bindings to set
|
||||
-- @param widgets : a table with widget style parameters
|
||||
-- @param objects : the list of tags to be displayed
|
||||
-- @param scr : the current screen
|
||||
local function list_update(w, buttons, label, data, widgets, objects, scr)
|
||||
-- Hack: if it has been registered as a widget in a wibox,
|
||||
-- it's w.len since __len meta does not work on table until Lua 5.2.
|
||||
-- Otherwise it's standard #w.
|
||||
local len = (w.len or #w) / 2
|
||||
-- Add more widgets
|
||||
if len < #objects then
|
||||
for i = len * 2 + 1, #objects * 2, 2 do
|
||||
local ib = capi.widget({ type = "imagebox", align = widgets.imagebox.align })
|
||||
local tb = capi.widget({ type = "textbox", align = widgets.textbox.align })
|
||||
|
||||
w[i] = ib
|
||||
w[i + 1] = tb
|
||||
w[i + 1]:margin({ left = widgets.textbox.margin.left, right = widgets.textbox.margin.right })
|
||||
w[i + 1].bg_resize = widgets.textbox.bg_resize or false
|
||||
w[i + 1].bg_align = widgets.textbox.bg_align or ""
|
||||
|
||||
if type(objects[math.floor(i / 2) + 1]) == "tag" then
|
||||
tagwidgets[ib] = objects[math.floor(i / 2) + 1]
|
||||
tagwidgets[tb] = objects[math.floor(i / 2) + 1]
|
||||
end
|
||||
end
|
||||
-- Remove widgets
|
||||
elseif len > #objects then
|
||||
for i = #objects * 2 + 1, len * 2, 2 do
|
||||
w[i] = nil
|
||||
w[i + 1] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- update widgets text
|
||||
for k = 1, #objects * 2, 2 do
|
||||
local o = objects[(k + 1) / 2]
|
||||
if not o then
|
||||
o = objects[(k-1) / 2]
|
||||
end
|
||||
if buttons then
|
||||
-- Use a local variable so that the garbage collector doesn't strike
|
||||
-- between now and the :buttons() call.
|
||||
local btns = data[o]
|
||||
if not btns then
|
||||
btns = {}
|
||||
data[o] = btns
|
||||
for kb, b in ipairs(buttons) do
|
||||
-- Create a proxy button object: it will receive the real
|
||||
-- press and release events, and will propagate them the the
|
||||
-- button object the user provided, but with the object as
|
||||
-- argument.
|
||||
local btn = capi.button { modifiers = b.modifiers, button = b.button }
|
||||
btn:add_signal("press", function () b:emit_signal("press", o) end)
|
||||
btn:add_signal("release", function () b:emit_signal("release", o) end)
|
||||
btns[#btns + 1] = btn
|
||||
end
|
||||
end
|
||||
w[k]:buttons(btns)
|
||||
w[k + 1]:buttons(btns)
|
||||
end
|
||||
|
||||
args = { screen = scr }
|
||||
local text, bg, bg_image, icon = label(o, args)
|
||||
|
||||
-- Check if we got a valid text here, it might contain e.g. broken utf8.
|
||||
if not pcall(function() w[k + 1].text = text end) then
|
||||
w[k + 1].text = "<i>Invalid</i>"
|
||||
end
|
||||
|
||||
w[k + 1].bg, w[k + 1].bg_image = bg, bg_image
|
||||
w[k].bg, w[k].image = bg, icon
|
||||
if not w[k + 1].text then
|
||||
w[k+1].visible = false
|
||||
else
|
||||
w[k+1].visible = true
|
||||
end
|
||||
if not w[k].image then
|
||||
w[k].visible = false
|
||||
else
|
||||
w[k].visible = true
|
||||
end
|
||||
end
|
||||
end
|
||||
--}}}
|
||||
|
||||
--{{{ taglist_update: update the taglist widget
|
||||
-- @param screen : the screen to draw the taglist for
|
||||
-- @param w : the taglist widget
|
||||
-- @param label : label function to use
|
||||
-- @param buttons : a table with button bindings to set
|
||||
-- @param widgets : a table with widget style parameters
|
||||
-- @param objects : the list of tags to be displayed
|
||||
local function taglist_update (screen, w, label, buttons, data, widgets)
|
||||
list_update(w, buttons, label, data, widgets, cachedtags, screen)
|
||||
end
|
||||
--}}}
|
||||
|
||||
--{{{ taglist: create a taglist widget for the shared tags
|
||||
-- @param screen : the screen to draw the taglist for
|
||||
-- @param label : label function to use
|
||||
-- @param buttons : a table with button bindings to set
|
||||
function taglist(screen, label, buttons)
|
||||
local w = {
|
||||
layout = layout.horizontal.leftright
|
||||
}
|
||||
local widgets = { }
|
||||
widgets.imagebox = { }
|
||||
widgets.textbox = { ["margin"] = { ["left"] = 0,
|
||||
["right"] = 0},
|
||||
["bg_resize"] = true
|
||||
}
|
||||
local data = setmetatable({}, { __mode = 'kv' })
|
||||
local u = function (s)
|
||||
if s == screen then
|
||||
taglist_update(s, w, label, buttons, data, widgets)
|
||||
end
|
||||
end
|
||||
local uc = function (c) return u(c.screen) end
|
||||
capi.client.add_signal("focus", uc)
|
||||
capi.client.add_signal("unfocus", uc)
|
||||
tag.attached_add_signal(screen, "property::selected", uc)
|
||||
tag.attached_add_signal(screen, "property::icon", uc)
|
||||
tag.attached_add_signal(screen, "property::hide", uc)
|
||||
tag.attached_add_signal(screen, "property::name", uc)
|
||||
capi.screen[screen]:add_signal("tag::attach", function(screen, tag)
|
||||
u(screen.index)
|
||||
end)
|
||||
capi.screen[screen]:add_signal("tag::detach", function(screen, tag)
|
||||
u(screen.index)
|
||||
end)
|
||||
capi.client.add_signal("new", function(c)
|
||||
c:add_signal("property::urgent", uc)
|
||||
c:add_signal("property::screen", function(c)
|
||||
-- If client change screen, refresh it anyway since we don't from
|
||||
-- which screen it was coming :-)
|
||||
u(screen)
|
||||
end)
|
||||
c:add_signal("tagged", uc)
|
||||
c:add_signal("untagged", uc)
|
||||
end)
|
||||
capi.client.add_signal("unmanage", uc)
|
||||
u(screen)
|
||||
return w
|
||||
end
|
||||
--}}}
|
||||
|
||||
--}}}
|
||||
|
||||
-- vim: fdm=marker:
|
29
rc/signals.lua
Normal file
29
rc/signals.lua
Normal file
|
@ -0,0 +1,29 @@
|
|||
-- 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 ((awful.layout.get(c.screen) ~= awful.layout.suit.magnifier or awful.client.getmaster(c.screen) == c)
|
||||
and awful.client.focus.filter(c)) then
|
||||
client.focus = c
|
||||
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
|
||||
end
|
||||
end)
|
||||
|
||||
client.add_signal("focus", function(c)
|
||||
c.border_color = beautiful.border_focus
|
||||
c.opacity = 1
|
||||
end)
|
||||
client.add_signal("unfocus", function(c)
|
||||
c.border_color = beautiful.border_normal
|
||||
c.opacity = 0.8
|
||||
end)
|
79
rc/start.lua
Normal file
79
rc/start.lua
Normal file
|
@ -0,0 +1,79 @@
|
|||
-- Startup
|
||||
|
||||
-- run a command only if the client does not already exist
|
||||
xrun = function(name, cmd)
|
||||
if os.execute("xwininfo -name '" .. name .. "' > /dev/null 2> /dev/null") == 0 then
|
||||
return
|
||||
end
|
||||
awful.util.spawn_with_shell(cmd or name)
|
||||
end
|
||||
|
||||
-- Setup display
|
||||
local xrandr = {
|
||||
naruto = "--output VGA1 --auto --output DVI1 --auto --left-of VGA1",
|
||||
neo = "--output HDMI-0 --auto --output DVI-0 --auto --right-of HDMI-0"
|
||||
}
|
||||
if xrandr[config.hostname] then
|
||||
os.execute("xrandr " .. xrandr[config.hostname])
|
||||
end
|
||||
|
||||
-- Spawn a composoting manager
|
||||
awful.util.spawn("unagi", false)
|
||||
|
||||
-- Start idempotent commands
|
||||
local execute = {
|
||||
-- Start PulseAudio
|
||||
"pulseaudio --check || pulseaudio -D",
|
||||
"xset -b", -- Disable bell
|
||||
-- Enable numlock
|
||||
"numlockx on",
|
||||
}
|
||||
|
||||
if config.hostname == "naruto" then
|
||||
execute = awful.util.table.join(
|
||||
execute, {
|
||||
-- Keyboard configuration
|
||||
"xset m 4 3", -- Mouse acceleration
|
||||
"setxkbmap us '' compose:rwin ctrl:nocaps",
|
||||
"xmodmap -e 'keysym Pause = XF86ScreenSaver'" })
|
||||
elseif config.hostname == "neo" then
|
||||
execute = awful.util.table.join(
|
||||
execute, {
|
||||
-- Keyboard configuration
|
||||
"xset m 3 3", -- Mouse acceleration
|
||||
"setxkbmap us '' compose:rwin ctrl:nocaps",
|
||||
"xmodmap -e 'keysym Pause = XF86ScreenSaver'"})
|
||||
elseif config.hostname == "guybrush" then
|
||||
execute = awful.util.table.join(
|
||||
execute, {
|
||||
-- Keyboard configuration
|
||||
"setxkbmap us '' compose:rctrl ctrl:nocaps",
|
||||
"xmodmap -e 'keysym XF86AudioPlay = XF86ScreenSaver'",
|
||||
-- Wheel emulation
|
||||
"xinput set-int-prop 'TPPS/2 IBM TrackPoint' 'Evdev Wheel Emulation' 8 1",
|
||||
"xinput set-int-prop 'TPPS/2 IBM TrackPoint' 'Evdev Wheel Emulation Button' 8 2",
|
||||
"xinput set-int-prop 'TPPS/2 IBM TrackPoint' 'Evdev Wheel Emulation Axes' 8 6 7 4 5",
|
||||
-- Disable touchpad
|
||||
"xinput set-int-prop 'SynPS/2 Synaptics TouchPad' 'Synaptics Off' 8 1"})
|
||||
end
|
||||
|
||||
os.execute(table.concat(execute, ";"))
|
||||
|
||||
-- Spawn various X programs
|
||||
startapps = function()
|
||||
xrun("polkit-gnome-authentication-agent-1",
|
||||
"/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1")
|
||||
xrun("Bluetooth Applet",
|
||||
"bluetooth-applet")
|
||||
|
||||
if config.hostname == "naruto" then
|
||||
xrun("Pidgin", "pidgin")
|
||||
elseif config.hostname == "neo" then
|
||||
xrun("Pidgin", "pidgin")
|
||||
xrun("keepassx", "keepassx -min -lock")
|
||||
xrun("Transmission", "transmission-gtk -m")
|
||||
elseif config.hostname == "guybrush" then
|
||||
xrun("keepassx", "keepassx -min -lock")
|
||||
-- xrun("nm-applet")
|
||||
end
|
||||
end
|
55
rc/tags.lua
Normal file
55
rc/tags.lua
Normal file
|
@ -0,0 +1,55 @@
|
|||
-- Tags
|
||||
|
||||
loadrc("sharetags")
|
||||
|
||||
local tags = { names = { "main", "emacs", "www", "im", 5 },
|
||||
layout = { awful.layout.suit.tile,
|
||||
awful.layout.suit.tile,
|
||||
awful.layout.suit.tile,
|
||||
awful.layout.suit.tile,
|
||||
awful.layout.suit.tile }}
|
||||
tags = sharetags.create_tags(tags.names, tags.layout)
|
||||
config.tags = {}
|
||||
|
||||
-- Compute the maximum number of digit we need, limited to 9
|
||||
keynumber = math.min(9, #tags)
|
||||
|
||||
-- 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, #tags do
|
||||
config.tags[tags[i].name] = tags[i]
|
||||
if i <= keynumber then
|
||||
config.keys.global = awful.util.table.join(
|
||||
config.keys.global,
|
||||
awful.key({ modkey }, "#" .. i + 9,
|
||||
function ()
|
||||
local t = tags[i]
|
||||
if t.screen ~= mouse.screen then
|
||||
sharetags.tag_move(t, mouse.screen)
|
||||
end
|
||||
awful.tag.viewonly(tags[i])
|
||||
end),
|
||||
awful.key({ modkey, "Control" }, "#" .. i + 9,
|
||||
function ()
|
||||
if tags[i] then
|
||||
awful.tag.viewtoggle(tags[i])
|
||||
end
|
||||
end),
|
||||
awful.key({ modkey, "Shift" }, "#" .. i + 9,
|
||||
function ()
|
||||
if client.focus and tags[i] then
|
||||
awful.client.movetotag(tags[i])
|
||||
end
|
||||
end),
|
||||
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
|
||||
function ()
|
||||
if client.focus and tags[i] then
|
||||
awful.client.toggletag(tags[i])
|
||||
end
|
||||
end))
|
||||
end
|
||||
end
|
||||
|
||||
awful.tag.setproperty(config.tags.emacs, "mwfact", 0.6) -- emacs
|
||||
awful.tag.setproperty(config.tags.www, "mwfact", 0.7) -- www
|
33
rc/theme.lua
Normal file
33
rc/theme.lua
Normal file
|
@ -0,0 +1,33 @@
|
|||
-- Theme
|
||||
beautiful.init(awful.util.getdir("config") .. "/themes/custom.lua")
|
||||
|
||||
-- GTK stuff: we choose Adwaita theme which seems to be the only one
|
||||
-- kept up-to-date with GTK2 and GTK3...
|
||||
|
||||
-- Also see: http://developer.gnome.org/gtk3/3.2/GtkSettings.html
|
||||
local gtk = 'gtk-font-name="' .. beautiful.font .. '"' .. [[
|
||||
|
||||
gtk-theme-name="Adwaita"
|
||||
gtk-icon-theme-name="gnome-wine"
|
||||
gtk-cursor-theme-name="oxy-cherry"
|
||||
gtk-cursor-theme-size=0
|
||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH
|
||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||
gtk-button-images=1
|
||||
gtk-menu-images=1
|
||||
gtk-xft-antialias=1
|
||||
gtk-xft-hinting=1
|
||||
gtk-xft-hintstyle="hintfull"
|
||||
gtk-xft-rgba="rgb"
|
||||
gtk-key-theme-name="Emacs"
|
||||
]]
|
||||
|
||||
local gtk2 = io.open(os.getenv("HOME") .. "/.gtkrc-2.0", "w")
|
||||
gtk2:write(gtk)
|
||||
gtk2:close()
|
||||
|
||||
-- GTK3 is the same, but no double quotes for strings
|
||||
local gtk3 = io.open(os.getenv("HOME") .. "/.config/gtk-3.0/settings.ini")
|
||||
gtk3:write("[Settings]\n")
|
||||
gtk3:write(gtk:gsub('"', ''))
|
||||
gtk3:close()
|
25
rc/wallpaper.lua
Normal file
25
rc/wallpaper.lua
Normal file
|
@ -0,0 +1,25 @@
|
|||
-- Change wallpaper
|
||||
|
||||
local wtimer = timer { timeout = 0 }
|
||||
|
||||
config.wallpaper = {}
|
||||
config.wallpaper.directory = awful.util.getdir("config") .. "/wallpapers"
|
||||
config.wallpaper.current = awful.util.getdir("cache") .. "/current-wallpaper.png"
|
||||
|
||||
-- We use fvwm-root because default backend for awsetbg does not seem
|
||||
-- to accept to set multiscreen wallpapers.
|
||||
local change = function()
|
||||
awful.util.spawn_with_shell(
|
||||
awful.util.getdir("config") .. "/bin/build-wallpaper " ..
|
||||
"--crop --directory " .. config.wallpaper.directory ..
|
||||
" --target " .. config.wallpaper.current ..
|
||||
"&& fvwm-root -r " .. config.wallpaper.current)
|
||||
end
|
||||
|
||||
wtimer:add_signal("timeout", function()
|
||||
change()
|
||||
wtimer:stop()
|
||||
wtimer.timeout = math.random(3000, 3600)
|
||||
wtimer:start()
|
||||
end)
|
||||
wtimer:start()
|
150
rc/widgets.lua
Normal file
150
rc/widgets.lua
Normal file
|
@ -0,0 +1,150 @@
|
|||
-- Widgets
|
||||
|
||||
require("vicious")
|
||||
|
||||
-- Separator
|
||||
local separator = widget({ type = "textbox" })
|
||||
separator.text = ' <span color="' .. beautiful.fg_widget_sep .. '">|</span> '
|
||||
|
||||
-- Date
|
||||
local datewidget = widget({ type = "textbox" })
|
||||
vicious.register(datewidget, vicious.widgets.date,
|
||||
'<span font="Terminus 8" color="' .. beautiful.fg_widget_clock .. '">%a %d/%m, %H:%M</span>', 61)
|
||||
|
||||
-- CPU usage
|
||||
local cpuwidget = widget({ type = "textbox" })
|
||||
cpuwidget.text = '<span font="Terminus 8" color="' .. beautiful.fg_widget_label .. '">CPU: </span>'
|
||||
local cpugraph = awful.widget.graph()
|
||||
cpugraph:set_width(45):set_height(12):set_max_value(100)
|
||||
cpugraph:set_border_color(beautiful.fg_widget_border)
|
||||
cpugraph:set_gradient_angle(0):set_gradient_colors({
|
||||
beautiful.fg_widget_start, beautiful.fg_widget_center, beautiful.fg_widget_end
|
||||
})
|
||||
vicious.register(cpugraph, vicious.widgets.cpu, "$1")
|
||||
local cpuvalue = widget({ type = "textbox" })
|
||||
vicious.register(cpuvalue, vicious.widgets.cpu,
|
||||
function (widget, args)
|
||||
return string.format('<span font="Terminus 8" color="' ..
|
||||
beautiful.fg_widget_value ..
|
||||
'"> %2d%%</span>', args[1])
|
||||
end)
|
||||
|
||||
-- Battery
|
||||
local batwidget = nil
|
||||
if config.hostname == "guybrush" then
|
||||
batwidget = widget({ type = "textbox" })
|
||||
vicious.register(batwidget, vicious.widgets.bat,
|
||||
'<span font="Terminus 8" color="' .. beautiful.fg_widget_label .. '">BAT: </span>' ..
|
||||
'<span font="Terminus 8" color="' .. beautiful.fg_widget_value .. '">$1 $2%</span>',
|
||||
61, "BAT0")
|
||||
end
|
||||
|
||||
-- Memory usage
|
||||
local memwidget = widget({ type = "textbox" })
|
||||
vicious.register(memwidget, vicious.widgets.mem,
|
||||
'<span font="Terminus 8" color="' .. beautiful.fg_widget_label .. '">Mem: </span>' ..
|
||||
'<span font="Terminus 8" color="' .. beautiful.fg_widget_value .. '">$1%</span>',
|
||||
13)
|
||||
|
||||
-- Volume level
|
||||
local volwidget = widget({ type = "textbox" })
|
||||
vicious.register(volwidget, vicious.widgets.volume,
|
||||
'<span font="Terminus 8" color="' .. beautiful.fg_widget_label .. '">Vol: </span>' ..
|
||||
'<span font="Terminus 8" color="' .. beautiful.fg_widget_value .. '">$2 $1%</span>',
|
||||
2, "Master")
|
||||
volwidget:buttons(awful.util.table.join(
|
||||
awful.button({ }, 1, function () awful.util.spawn("pavucontrol", false) end),
|
||||
awful.button({ }, 4, function () awful.util.spawn("amixer -q -c 0 set Master 2dB+", false) end),
|
||||
awful.button({ }, 5, function () awful.util.spawn("amixer -q -c 0 set Master 2dB-", false) end)
|
||||
))
|
||||
|
||||
local systray = widget({ type = "systray" })
|
||||
|
||||
-- {{{ Wibox initialisation
|
||||
local wibox = {}
|
||||
local promptbox = {}
|
||||
local layoutbox = {}
|
||||
|
||||
local taglist = {}
|
||||
taglist.buttons = awful.util.table.join(
|
||||
awful.button({ }, 1,
|
||||
function(t)
|
||||
if t.screen ~= mouse.screen then
|
||||
sharetags.tag_move(t, mouse.screen)
|
||||
end
|
||||
awful.tag.viewonly(t)
|
||||
end),
|
||||
awful.button({ modkey }, 1, awful.client.movetotag),
|
||||
awful.button({ }, 3,
|
||||
function(t)
|
||||
if t.screen ~= mouse.screen then
|
||||
sharetags.tag_move(t, mouse.screen)
|
||||
end
|
||||
awful.tag.viewtoggle(t)
|
||||
end),
|
||||
awful.button({ modkey }, 3, awful.client.toggletag),
|
||||
awful.button({ }, 4, awful.tag.viewnext),
|
||||
awful.button({ }, 5, awful.tag.viewprev))
|
||||
|
||||
local tasklist = {}
|
||||
tasklist.buttons = awful.util.table.join(
|
||||
awful.button({ }, 1, function (c)
|
||||
if c == client.focus then
|
||||
c.minimized = true
|
||||
else
|
||||
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
|
||||
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)
|
||||
return awful.widget.tasklist.label.currenttags(c, s)
|
||||
end, tasklist.buttons)
|
||||
|
||||
-- Create the taglist
|
||||
taglist[s] = sharetags.taglist(s, sharetags.label.all, taglist.buttons)
|
||||
-- Create the wibox
|
||||
wibox[s] = awful.wibox({ screen = s,
|
||||
fg = beautiful.fg_normal,
|
||||
bg = beautiful.bg_widget,
|
||||
position = "top",
|
||||
height = 14,
|
||||
})
|
||||
-- Add widgets to the wibox
|
||||
local onfirst = function(what)
|
||||
if s == 1 then return what end
|
||||
return nil
|
||||
end
|
||||
local onsecond = function(what)
|
||||
if s == 2 or screen.count() == 1 then return what end
|
||||
return nil
|
||||
end
|
||||
|
||||
wibox[s].widgets = {
|
||||
{
|
||||
taglist[s], layoutbox[s],
|
||||
separator, promptbox[s],
|
||||
layout = awful.widget.layout.horizontal.leftright
|
||||
},
|
||||
onfirst(systray), onfirst(seperator),
|
||||
datewidget, separator,
|
||||
onsecond(volwidget), onsecond(separator),
|
||||
onsecond(batwidget), onsecond(batwidget and separator or nil),
|
||||
onfirst(memwidget), onfirst(separator),
|
||||
onfirst(cpuvalue), onfirst(cpugraph.widget), onfirst(cpuwidget), onfirst(separator),
|
||||
tasklist[s], separator,
|
||||
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))
|
9
rc/xlock.lua
Normal file
9
rc/xlock.lua
Normal file
|
@ -0,0 +1,9 @@
|
|||
-- Lockscreen
|
||||
|
||||
xrun("xautolock",
|
||||
"xautolock -time 5 -locker 'i3lock -n -i " ..
|
||||
awful.util.getdir("cache") .. "/current-wallpaper.png'")
|
||||
|
||||
config.keys.global = awful.util.table.join(
|
||||
config.keys.global,
|
||||
awful.key({}, "XF86ScreenSaver", function() awful.util.spawn("xautolock -locknow", false) end))
|
22
themes/custom.lua
Normal file
22
themes/custom.lua
Normal file
|
@ -0,0 +1,22 @@
|
|||
-- Small modifications to anrxc's zenburn theme
|
||||
|
||||
local theme = loadrc("../themes/nice-and-clean-theme/theme")
|
||||
if theme then
|
||||
theme.wallpaper_cmd = { "/bin/true" }
|
||||
theme.font = "Cantarell 9"
|
||||
|
||||
theme.bg_normal = theme.bg_normal .. "99"
|
||||
theme.bg_focus = theme.bg_focus .. "99"
|
||||
theme.bg_urgent = theme.bg_urgent .. "99"
|
||||
theme.bg_minimize = theme.bg_minimize .. "99"
|
||||
theme.bg_widget = "#00000099"
|
||||
theme.fg_widget_label = "#708090"
|
||||
theme.fg_widget_value = "#FFFFFF"
|
||||
theme.fg_widget_sep = "#FFFFFF"
|
||||
theme.fg_widget_border = "#FFFFFF"
|
||||
theme.fg_widget_clock = "#FF7F00"
|
||||
theme.fg_widget_end = "#FFFFFF"
|
||||
theme.fg_widget_center = "#FFCCCC"
|
||||
theme.fg_widget_start = "#FF0000"
|
||||
return theme
|
||||
end
|
1
themes/nice-and-clean-theme
Submodule
1
themes/nice-and-clean-theme
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 687d77ae6c2c2cfc38ca85f226006244384560d6
|
Loading…
Add table
Add a link
Reference in a new issue