--[[ Author: Etan Reisner Email: deryni@unreliablesource.net Summary: Allows for automatic per-cwin/per-frame switching of the active Xkb group. Last Updated: 2009-01-20 License: MIT Copyright (c) Etan Reisner 2008-2009 --]] --[[ Usage: The XkbGroup names can be found by inspecting the table returned from frame_xkb.group_names or by building and running the xkb_group_names binary. To inspect the table returned by frame_xkb.group_names run the following code in the Lua query (Mod1+F3). It will print out one group "id - name" pairs. for i,v in ipairs(frame_xkb.group_names()) do print(i.." - "..v) end This script sets XkbGroup(1-4) grattr:s on frames designating what Xkb group the script has them locked to when you focus it. Adding sections like de.substyle("*-*-*-XkbGroup1", { background_colour = "white", }), to your theme's de.defstyle("tab-frame", {...}) style will cause them to be shown. Use xkb_tag(reg, xkbgroup) to set a frame/cwin as having an XkbGroup. Use xkb_untag(reg) to remove an XkbGroup from a frame/cwin. --]] if not frame_xkb then if not pcall(dopath, "frame_xkb") then warn("Unable to load the frame_xkb module. Make sure it is installed in the correct location.") return end end local xkbcwins = setmetatable({}, {__mode="k"}) local xkbframes = setmetatable({}, {__mode="k"}) local xkbgroup_display_names = {} function set_xkbgroup_display_names(dn) xkbgroup_display_names = dn end local function update_xkbgroup(xkbgroup) if xkbgroup_display_names and xkbgroup_display_names[xkbgroup] then mod_statusbar.inform("xkbgroup", xkbgroup_display_names[xkbgroup]) else mod_statusbar.inform("xkbgroup", xkbgroup) end frame_xkb.lock_group_by_name(xkbgroup) mod_statusbar.update() end -- This may want to be changed to record when it changes the xkb group so it -- can undo the change, currently is resets the group to the default when the -- user switches to any cwin that isn't tagged as wanting a certain group to -- be active. local function region_notify(reg, action) if (action ~= "activated") then return end local xkbgroup local frame = ioncore.find_manager(reg, "WFrame") if not frame then return end if obj_is(reg, "WClientWin") then local winprop = ioncore.getwinprop(reg) -- If we don't have an xkbgroup for this cwin, check the managing -- frame. xkbgroup = winprop and winprop.xkbgroup or xkbcwins[reg] or xkbframes[frame] elseif obj_is(reg, "WFrame") and frame:current() then -- If we have something inside the frame then it is likely going to -- get its own call to region_notify and doing anything here is -- useless. return end xkbgroup = xkbgroup or xkbframes[frame] -- Use the default group if we don't have one already. ioncore.defer(function() xkbgroup = xkbgroup or frame_xkb.group_names()[1] update_xkbgroup(xkbgroup) end) end local function save_frames() local tmptab = {} for frame,xkbgroup in pairs(xkbframes) do local framename = frame:name() if framename then tmptab[framename] = xkbgroup end end ioncore.write_savefile("saved_cwin_frame_xkb", tmptab) end local function load_frames() local frames = ioncore.read_savefile("saved_cwin_frame_xkb") or {} for framename,xkbgroup in pairs(frames) do local frame = ioncore.lookup_region(framename) if frame and frame_xkb.get_group(xkbgroup) then handle_frame(frame, xkbgroup) end end end local function handle_cwin(cwin, xkbgroup) xkbcwins[cwin] = xkbgroup if cwin == ioncore.current() then update_xkbgroup(xkbgroup or frame_xkb.group_names()[1]) end end local function handle_frame(frame, xkbgroup) local grattrs = {"XkbGroup1", "XkbGroup2", "XkbGroup3", "XkbGroup4"} xkbframes[frame] = xkbgroup if frame == ioncore.find_manager(ioncore.current(), "WFrame") then update_xkbgroup(xkbgroup or frame_xkb.group_names()[1]) end local groupid if xkbgroup then groupid = frame_xkb.get_group(xkbgroup) if not groupid then return end groupid = "Xkb"..groupid -- Don't bother setting the grattr:s when we already have the right -- grattr set. Only set/unset them when something has changed. if WFrame.is_grattr and frame:is_grattr(groupid) then return end end for i = 1, 4 do local grattr = grattrs[i] frame:set_grattr(grattr, (groupid == grattr) and "set" or "unset") end end function xkb_tag(reg, xkbgroup) if xkbgroup and (not frame_xkb.get_group(xkbgroup)) then return end if obj_is(reg, "WClientWin") then handle_cwin(reg, xkbgroup) elseif obj_is(reg, "WFrame") then handle_frame(reg, xkbgroup) end end function xkb_tag_query(mplex) local function complete_group(str) local tab = {None = true} for i,v in ipairs(frame_xkb.group_names()) do tab[v] = true end return mod_query.complete_keys(tab, str, true, true) end local function xkb_tag_helper(reg, xkbgroup) if xkbgroup == "None" then xkbgroup = nil end xkb_tag(reg, xkbgroup) end mod_query.query(mplex, TR("Tag current region with group:"), nil, xkb_tag_helper, mod_query.make_completor(complete_group), "xkbgroup") end do local i = {} local x = frame_xkb.group_names() function xkb_cyclic_tag(reg) if not reg then return end i[reg] = (not i[reg]) and 1 or i[reg] i[reg] = x[i[reg] + 1] and (i[reg] + 1) or 1 return xkb_tag(reg, x[i[reg]]) end end -- Init local hooktab = {region_notify_hook = region_notify, ioncore_snapshot_hook = save_frames, ioncore_deinit_hook = save_frames} for hook,fun in pairs(hooktab) do local hook = ioncore.get_hook(hook) if hook then hook:add(fun) end end load_frames()