1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
---------------------------------
-- Author: Andrei Thorp --
-- Copyright 2010 Andrei Thorp --
---------------------------------
-- Dependencies: setxkbmap (shell command)
-- Ideas:
-- * user specified rewrite table: convert us(dvorak) to "Dvorak"
-- * use formatting system to allow people to format their text widgets
-- * allow the user to override the text widget with some other widget
-- * filter out the current layout from the menu that appears on click
-- * let user configure the quick update delay (1 second) in case their
-- computer is unusually slow or quick or something
local setmetatable = setmetatable
local pairs = pairs
local ipairs = ipairs
local io = {
popen = io.popen
}
local awful = require("awful")
local wibox = require("wibox")
local lib = {
hooks = require("obvious.lib.hooks"),
markup = require("obvious.lib.markup")
}
local defaults = {}
defaults.layouts = {}
defaults.menu = nil
defaults.widget = wibox.widget.textbox()
defaults.widget:set_text("...")
local current_index = 1
-- Clone the defaults to the used settings
local settings = {}
for key, value in pairs(defaults) do
settings[key] = value
end
-- forward declaration of functions
local update
local set_layouts
-- Updates once after a short delay and then unregisters its timer
local function delayed_update_once(start)
if start == true then
lib.hooks.timer.register(1, 1, delayed_update_once, "One-off update for keymap widget")
lib.hooks.timer.start(delayed_update_once)
else
update()
lib.hooks.timer.unregister(delayed_update_once)
end
end
local setup_done = false
local function init_once()
if setup_done then
return
end
lib.hooks.timer.register(5, 60, update, "Update for the keymap widget")
lib.hooks.timer.start(update)
delayed_update_once(true)
setup_done = true
end
local function switch_keymap(layout_string)
awful.util.spawn("setxkbmap \"" .. layout_string .. "\"")
delayed_update_once(true)
end
local function init(widget)
init_once()
-- Use the default widget if not specified
if widget then
settings.widget = widget
end
local layouts = settings.layouts
settings.widget.rotate_layout = function()
current_index = current_index + 1
if current_index > #layouts then
current_index = 1
end
switch_keymap(layouts[current_index])
end
-- Reconfigure the menu immediately
set_layouts(settings.layouts)
-- Set up the on-click menu event
settings.widget:buttons(awful.util.table.join(
awful.button({ }, 1, function() settings.menu:toggle() end)
))
return settings.widget
end
-- Returns the current keymap, as discovered from setxkbmap
local function get_current_keymap()
local fd = io.popen("setxkbmap -print")
if not fd then return end
for line in fd:lines() do
if line:match("xkb_symbols") then
local keymap = line:match('%+[a-zA-Z0-9()]*%+')
fd:close()
if not keymap then
return "unknown layout"
else
return keymap:sub(2, -2)
end
end
end
fd:close()
return "unknown layout"
end
--[[local]] function set_layouts(layouts_table)
settings.layouts = layouts_table or settings.layouts
local newitems = {}
for index, value in ipairs(settings.layouts) do
newitems[index] = { value, function()
current_index = index
switch_keymap(value)
end }
end
settings.menu = awful.menu.new({
id = "keymap_switch",
items = newitems
})
end
--[[local]] function update()
settings.widget:set_markup(get_current_keymap())
end
return setmetatable({
set_layouts = set_layouts,
update = update,
}, { __call = function() return init(settings.widget) end }) -- TODO let the user specify widget here
-- vim:ft=lua:ts=2:sw=2:sts=2:tw=80:et
|