LINUX.ORG.RU

Переключение раскладки в Ионе, ч.2


0

0

Ну что, наваял скриптик.

1. После переключения на английскую раскладку (командочкой setxkbmap us я это делаю) перестают работать все мои привязки клавиш, начинающиеся с Mod4+. Те, что с Mod4+Control+, продолжают спокойно работать. С Mod4+Shift+ тоже работают. В окошках с русской раскладкой (при попадании в которые из английских выполняется setxkbmap ru winkeys) работают _все_ привязки, в том числе и те, что с голым Mod4+. Но самая мистика в том, что если вызвать ровно ту же самую команду setxkbmap us вручную, то опять же все юиндинги работают, и только после того, как её вызывает Ион, они ломаются. Я для проверки создал внешний скриптик, который мне в логи говорил, что его запустили, и затем вызывал setxkbmap, - так вот после того, как его запускал Ион - привязки ломались, а после того, как это делал я - работали. Не очень представляю, как такое может быть. Переключился пока на Mod4+Shift+, но блин неудобно это. У кого-нибудь есть идеи?

Это собственно единственная возникшая проблема, причём из разряда мистических. Я (в смысле скрипт) тут точно не виноват, иксы вроде тоже, разве что Ион, но трудно представить, каким образом.

2. Надо бы лампочкой scroll мигать, но я не умею. Кто знает команду для этого?

3. Замечание. Чтобы использовать для переключения раскладок Caps_Lock (как это делаю я), надо к setxkbmap дописывать grp:caps_toggle. Просто для того, чтоб иксы перестали его использовать по прямому назначению (для переключения регистра). Без этого переключаются сразу и раскладка, и регистр.

AiLr, жду отзыва. :) Если предложений по улучшению нет (особенно по решению первой проблемы), то отправляю это дело автору Ion.

★★★★★

-- xkbion.lua

-- (c) Sergey Redin
-- Thanks:
-- smersh at users.sf.net (author of xkbind) for the original idea
-- AiLr for the discussion

--[[

-- This script allows you to use independent keyboard layouts for different windows in Ion3.
-- It uses a window property to store the XKB groups, so you can restart Ion without losing
-- settings for each window.
-- Put the following lines into your cfg_ion.lua:

dopath("xkbion.lua")
xkbion_set {
    {name="EN", command="setxkbmap us -option grp:caps_toggle"},
    {name="RU", command="setxkbmap ru winkeys -option grp:caps_toggle"},
    key="Caps_Lock",
    statusname = "xkbion",
}

-- Edit this to suit your needs.
-- At least onw group definition must be present.
-- "name" is only neseccary if you want to use mod_statusbar to indicate current XKB group.
-- "command" is also unneseccary but xkbion.lua is not pariculary useful without it. :)
-- The same thing for "key".
-- If you set "statusname" to "xkbion", you can use this line in cfg_statusbar.lua:

template="... %xkbion ...",

-- You can call xkbion_set more than once with different args if you really know what you're
-- doing. The last parameter, atomname, is useful if you need it. I have tested it with:

xkbion_set {
    {name="1"},
    {name="2"},
    {name="3"},
    key="Menu",
    statusname="num",
    atomname="XKBION_NUM",
}

]]



function xkbion_set (groups) -- the only global created by xkbion.lua

    if not groups or type(groups) ~= "table" then error("bad args") end
    if not groups[1] or type(groups[1]) ~= "table" then
        error("default group is undefined")
    end

    -- window_group_prop(w) - get XKBION_GROUP integer property of window `w' (set it to 1 if it's not yet defined)
    -- window_group_prop(w, group) - set XKBION_GROUP property of window `w' to integer `group'
    -- "XKBION_GROUP" is just the default name
    local window_group_prop
    do
        local XA_INTEGER = 19
        local atom = ioncore.x_intern_atom( tostring( groups.atomname or "XKBION_GROUP" ) )
        if not atom or type(atom) ~= "number" then
            error("Cannot intern atom " .. atomname)
        end
        window_group_prop = function(w, gnum)
            if not w or type(w) ~= "userdata" or not w.xid or type(w.xid) ~= "function" then return 1 end
            local xid = tonumber( w:xid() )
            if gnum == nil then
               local t = ioncore.x_get_window_property( xid, atom, XA_INTEGER, 1, true )
                if t and type(t) == "table" and t[1] ~= nil then
                    do return tonumber(t[1]) end
                else
                    gnum = 1
                end
            else
                gnum = tonumber(gnum)
            end
            -- we're here if the second argument is not set or if the window does not have our property yet
            ioncore.defer( function()
                ioncore.x_change_property( xid, atom, XA_INTEGER, 32, "replace", {gnum} )
            end )
            return gnum
        end
    end
    
    local set_group
    do
        local current_gnum = 1
        local first_time = true
        local statusname = groups.statusname
        if type(statusname) ~= "string" then statusname = nil end
        set_group = function(w, do_increment)
            local gnum
            if w then
                gnum = window_group_prop(w)
            else
                gnum = 1
            end
            if do_increment then gnum = gnum + 1 end
            local g = groups[gnum]
            if not g then gnum, g = 1, groups[1] end
            if not g then return end -- error in settings, groups[1] not defined
            if first_time then
                first_time = false
            elseif gnum == current_gnum then
                return
            end
            window_group_prop(w, gnum)
            if g.command then
                ioncore.exec(g.command)
            end
            current_gnum = gnum
            local group_name = g.name
            if statusname and group_name and type(group_name) == "string" then
                mod_statusbar.inform(statusname, g.name)
                ioncore.defer(mod_statusbar.update)
            end
        end
    end
    
    ioncore.get_hook("region_activated_hook"):add(
        function(reg) 
            if tostring(reg.__typename) == "WClientWin" then
                set_group(reg)
            end
        end
    )

    local key = groups.key
    if key and type(key) == "string" then
        defbindings("WMPlex", {
            kpress(key, function (_, _sub) set_group(_sub, true)  end, "_sub:WClientWin")
        })
    end

    set_group() -- initialize

end -- xkbion_set()

Teak ★★★★★
() автор топика

Попробуй переключать с помощью xkbsel (command-line interface for selecting the keyboards, suitable for installing as action bound to some key combination in a window manager, inclusion in scripts or plain command-line usage.)

AiLr ★★
()
Ответ на: комментарий от AiLr

объясните мне одно,
зачем все это, когда можно просто
добавить
в хорг.конф строчку для переключения раскладок
и там же опция чтобы скролл светился/не светился
????????????????

Lockywolf ★★★
()
Ответ на: комментарий от sergej

Меня пока устраивает xxkb, но ссылку сохранил на всякий случай...

Хочу с Num/Caps Lock также сделать...

sergej ★★★★★
()
Ответ на: комментарий от AiLr

Tuomo молча, ничего не отвечая, добавил мой скриптик :)

http://modeemi.fi/~tuomov/repos/ion-scripts-3/scripts/xkbion.lua

Короче на xkbsel я погляжу, но наверное не сегодня и даже не завтра. А вообще спасибо, не знал о такой программке. Хотя я уже к новым привязкам привык :)

Скриптик мой полностью пригоден для переключения CapsLock/Numlock при одном условии - если вы найдёте/напишете командочку, которая переключает соответствующую вещь. Вообще он очень обобщённо написан, можно сразу несколько раз его вызвать из cfg_ion.lua и хранить разные свойства для каждого окна. Но сначала надо, чтобы была команда, которая умеет их собственно переключать. Для раскладок это setxkbmap или xkbsel, а есть ли что для CapsLock - это уже сами смотрите.

Teak ★★★★★
() автор топика
Ответ на: комментарий от Teak

Xkbsel глючит в седьмых иксах.

А вообще для нормального переключения раскладки достаточно одного простого вызова XkbLockGroup. Это делает к примеру fookb (fookb.c:259), но оно не имеет опций коммандной строки ;( Завтра на шашлыки, так что если возьмусь переделывать fookb, то релиз будет где-то на следующей неделе...

AiLr ★★
()
Ответ на: комментарий от AiLr

> достаточно одного простого вызова XkbLockGroup.

Оно бы хорошо, но как я сишную функцию буду из Луа вызывать? Только если расширение писать. Но его в ion3-scripts точно не добавят :)

Кстати написать расширение - это мысль, loadlib же никто не отменял. Кинуть so-шку рядом со скриптиком в .ion3, и не надо вызывать глючный setxkbmap, и вообще форкаться при каждом переключении раскладки.

Всё, сажусь писать расширение :)

Teak ★★★★★
() автор топика
Ответ на: комментарий от Teak

Кстати заметил один глюк от setxkbmap - с латинской раскладкой Alt-Enter разворачивает окна, но не сворачивает, а с русской работает нормально. Буду переделывать fookb, как с шашлыка приеду ;)

AiLr ★★
()
Ответ на: комментарий от AiLr

Думаю, не понадобится. :)

Послал Tuomo патчик на Ион, который добавляет Lua-интерфейс к XkbLockGroup, ну и добавил одну строчку в сам скрипт, чтобы он это дело использовал. Изменения очень маленькие, по сути в Ион добавляется одна функция с телом из одной строки, так что не вижу, почему бы ему их не принять. В общем, ждите ебилдов :)

У меня всё работает на пять, вернулся к старым привязкам, они всё же намного удобнее ;)

Teak ★★★★★
() автор топика
Ответ на: комментарий от AiLr

Это кстати тот же самый глюк. У меня все привязки с MOD1 полетели в летинской раскладке, только у меня MOD1 - это "Mod4+", то есть виндовская кнопочка, а у тебя - дефолтный Alt.

Шайтан, блин. Я долго копался, но так и не понял, как такое вообще может быть. Да и чёрт с ним. :)

Teak ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.