понедельник, 11 апреля 2011 г.

Awesome WM & keyboard layout indicator.

Люди не знающие что такое awesome и не интересующиеся вопросами этого WM дальше могут вообще не читать. ;) Для общего понимания такие читатели могут сходить по тегам awesome и tiled wm и почитать что к чему. Ладно, это все лирика. И так...

Недавно я обновился до ubuntu 10.10. Все прошло довольно гладко, не считая одного мелкого обстоятельства: пропал нафиг индикатор клавиатуры. :( В замен его, как пишут в баг-репортах на лаунчпаде, появилась ugly, unusable icon! :) Как выяснилось позже он в общем то не пропадал, а просто вместо одной иконки с надписью USA/Rus, команда разработчиков почему-то решила сделать 2 иконки: одна с этими самыми надписями, а вторая - с клавиатурой. Нафиг это надо - мне лично не понятно. Ну да ладно, сделали и сделали. Но есть одно "но": если использовать этот индикатор в чем-то отличном от гнома, но клавиатура рисуется, а вот иконка с собственно информацией - нет. :( Почему - не знаю.

Пришлось срочно принимать меры. Сначала я вернулся к классическому методу: awesome + skb + timer. Все бы ничего, но мне не нравится в этом решении:

  1. таймер, ибо выполнение каждую секунду внешней программы, это как-то не очень красиво
  2. даже при секундном опросе skb иногда наблюдается задержка отображения при переключении раскладки - не критично, но "не аккуратненько, доктор" :)
Вообще не плохо было бы, что бы система сама нам говорила, когда раскладка изменилась. И уже от этого события менять отображение. И такой механизм в awesome есть! Это dbus. :) И так от болтовни перейдем к делу. Не буду утруждать вас теорией, если будут вопросы - спрашивайте. Приведу сразу кусок конфига:

--- {{{ keyboard indicator
mykeyindicator = widget({ type = "imagebox", align = "right" })

function mykey_update()
    local fd = io.popen("skb a")
    local key_layout = fd:read()
    fd:close()
    mykeyindicator.image = image(home_dir .. "/.icons/flags/" .. key_layout .. ".png")
    return
end 

dbus.add_match("session", "member='LayoutUpdated'")
dbus.add_signal("org.ayatana.dbusmenu", mykey_update)
--- keyboard indicator }}}

Собственно тут все просто: создаем виджет imagebox. Делаем функцию, которая запускает skb и читает его вывод. Вывод у него простой: если раскладка была английская - выдается строка "USA", если русская - "Rus". В папке ~/.icons/flags/ у меня лежать две картинки USA.png и Rus.png. В соответствии с результатом выставляем в виджет нужную картинку.
А теперь самое главное! Немного магии, которая заставит это все работать. :) Это как раз последние 2 строки с dbus:

  • первая (dbus.add_match) - создает правило совпадения, которая срабатывает при появлении в dbus сообщения об изменении раскладки
  • вторая (dbus.add_signal) - создает сигнал, который и будет вызывать нашу функцию, при срабатывании совпадения
Вот собственно и все. :) Имеем то, что хотели: опрос идет только когда надо, переключатель срабатывает без задержек, как только в dbus появляется сигнал. :)