Include mod_xkbevents instead of using a submodule
[notion/jeffpc.git] / mod_xkbevents / xkbion.lua
blob16aa153bb6724780edf8600ed4d047456ae25799
1 -- xkbion.lua
2 -- TODO: make xkbion_set understand some simple presets
4 -- (c) Sergey Redin <sergey at redin.info>
5 -- Thanks:
6 -- smersh at users.sf.net (author of xkbind) for the original idea
8 --[[
10 -- This script allows you to use independent keyboard layouts for different windows in Anion3.
11 -- It uses a window property to store the XKB groups, so you can restart Ion without losing
12 -- settings for each window.
14 -- Example usage. This is what I have in my cfg_ion.lua:
16 dopath("mod_xkbevents")
17 dopath("xkbion.lua")
18 xkbion_set {
19 {name="EN", hint="", action = function() mod_xkbevents.lock_group(0) end},
20 {name="RU", hint="important", action = function() mod_xkbevents.lock_group(1) end},
21 key="Caps_Lock",
22 statusname = "xkbion",
24 xkbion_set {
25 {name="NUM", command="numlockx on"},
26 {name="---", command="numlockx off"},
27 key="Num_Lock",
28 statusname="num",
29 atomname="XKBION_NUM",
31 xkbion_set {
32 {name="----", hint="", action = function() mod_xkbevents.lock_modifiers(2, 0) end},
33 {name="CAPS", hint="critical", action = function() mod_xkbevents.lock_modifiers(2, 2) end},
34 key="Caps_Lock",
35 statusname = "caps",
36 atomname="XKBION_CAPS",
39 -- Edit this to suit your needs.
40 -- Please note, if you want to use Caps_Lock key to change the keyboard groups like I do,
41 -- do not forget to add "grp:caps_toggle" to your XKB settings, just to prevent X from using
42 -- this key also for swiching keyboard registers.
44 -- At least one group definition must be present.
45 -- "name" is only neseccary if you want to use mod_statusbar to indicate current XKB group.
46 -- "hint" is only necessary if you want to highlight your XKB group in statusbar, possible
47 -- values are standard values provided by the mod_statusbar: important, normal, critical
48 -- "command" and "action" are also unneseccary but xkbion.lua is not particulary useful
49 -- without them. :) The same thing for "key".
51 -- The last thing to say about xkbion_set() parameters is that if you call xkbion_set
52 -- more than once (like I do it for XKB groups and NumLock state) you must choose different
53 -- "atomname" values. The default for atomname is XKBION_GROUP.
55 -- The second xkbion_set() call (numlock section) is here mostly for the example. Most users
56 -- will need only one call, for changing XKB group. Please also note that you can define more
57 -- than two groups in call to xkbion_set().
59 -- You can use this line in cfg_statusbar.lua to indicate the current XKB group:
61 -- template="... %xkbion ...",
63 -- If your Ion does not have mod_xkb, you may try the following:
65 -- xkbion_set {
66 -- {name="EN", command="setxkbmap us -option grp:caps_toggle"},
67 -- {name="RU", command="setxkbmap ru winkeys -option grp:caps_toggle"},
68 -- key="Caps_Lock",
69 -- statusname = "xkbion",
70 -- }
74 function xkbion_set (groups) -- the only global created by xkbion.lua
76 if not groups or type(groups) ~= "table" then error("bad args") end
77 if not groups[1] or type(groups[1]) ~= "table" then
78 error("default group is undefined")
79 end
81 -- window_group_prop(w) - get XKBION_GROUP integer property of window `w' (set it to 1 if it's not yet defined)
82 -- window_group_prop(w, group) - set XKBION_GROUP property of window `w' to integer `group'
83 -- "XKBION_GROUP" is just the default name
84 local window_group_prop
86 local XA_INTEGER = 19
87 local atom = notioncore.x_intern_atom( tostring( groups.atomname or "XKBION_GROUP" ) )
88 if not atom or type(atom) ~= "number" then
89 error("Cannot intern atom " .. atomname)
90 end
91 window_group_prop = function(w, gnum)
92 if not w or type(w) ~= "userdata" or not w.xid or type(w.xid) ~= "function" then return 1 end
93 local xid = tonumber( w:xid() )
94 if gnum == nil then
95 local t = notioncore.x_get_window_property( xid, atom, XA_INTEGER, 1, true )
96 if t and type(t) == "table" and t[1] ~= nil then
97 do return tonumber(t[1]) end
98 else
99 gnum = 1
101 else
102 gnum = tonumber(gnum)
104 -- we're here if the second argument is set or if the window does not have our property yet
105 notioncore.defer( function()
106 notioncore.x_change_property( xid, atom, XA_INTEGER, 32, "replace", {gnum} )
107 end )
108 return gnum
112 local set_group
114 local current_gnum = 1
115 local first_time = true
116 local statusname = groups.statusname
117 if statusname and type(statusname) ~= "string" then statusname = nil end
118 set_group = function(w, do_increment)
119 local gnum
120 if w then
121 gnum = window_group_prop(w)
122 else
123 gnum = 1
125 if do_increment then gnum = gnum + 1 end
126 local g = groups[gnum]
127 if not g then gnum, g = 1, groups[1] end
128 if not g then return end -- error in settings, groups[1] not defined
129 if first_time then
130 first_time = false
131 elseif gnum == current_gnum then
132 return
134 window_group_prop(w, gnum) -- it's OK to call it even it `w' is nil
135 if g.command then
136 notioncore.exec(g.command)
138 if g.action then notioncore.defer(g.action) end
139 current_gnum = gnum
140 local group_name = g.name
141 local hint_name = g.hint
142 if statusname and group_name and type(group_name) == "string" then
143 mod_statusbar.inform(statusname, group_name)
144 mod_statusbar.inform(statusname.."_hint", hint_name)
145 notioncore.defer(mod_statusbar.update)
150 notioncore.get_hook("region_notify_hook"):add(
151 function(reg, action)
152 if (reg ~= nil) and (tostring(reg.__typename) == "WClientWin") then
153 if (action == "activated") or (action == "pseudoactivated") then
154 set_group(reg)
160 local key = groups.key
161 if key and type(key) == "string" then
162 defbindings("WClientWin", {
163 kpress(key, function (_, _sub) set_group(_, true) end)
167 set_group() -- initialize
169 end -- xkbion_set()