15 Sep 2013 17:00:31
WM Awesome, Conky and Compton Composite Manager. Tip and Tricks. Focus, Shadow Problems.
Prevent compton draw shadow on conky window. Write lua behavior to avoid focusing conky and cairo-dock windows by Awesome WM.Настраивать будем на примере операционной системы Archlinux
Проблемы с которыми я столкнулся при желании запустить conky:
Оглавление
- Используемый мной композитный менеджер compton рисовал тени на окне с conky.
- При переключении тагов в awesome ранее фокусированные окна теряли фокус, мало того история открытых окон забивалась неиспользуемыми окнами, что приводило к неудобному переключению между ними.
- При инициализации системы конки находились в некорректной позиции.
Тени от композитника:
В конфигурационном файле conky ~/.conkyrc есть аттрибут own_window_type, он может принимать значения desktop | normal | panel | overriden, если у вас настроен overriden - то X11 не задает окну class, name и прочие идентификаторы для того чтобы композитник мог идентифицировать окно, мало того - данное окно выходит из под контроля оконного менеджера, но тем не менее тень на нем остается, после разных вариантов - я остановился на типе окна normal, вот конфиг:
background no update_interval 1 cpu_avg_samples 2 net_avg_samples 2 temperature_unit celsius double_buffer yes no_buffers yes text_buffer_size 2048 gap_x 0 gap_y 0 minimum_size 305 450 maximum_width 303 own_window yes own_window_type normal own_window_title conky own_window_class conky own_window_transparent yes own_window_argb_visual yes own_window_hints undecorate,sticky,skip_taskbar,skip_pager,below border_inner_margin 0 border_outer_margin 0 alignment tr draw_shades yes draw_outline no draw_borders no draw_graph_borders no override_utf8_locale yes use_xft yes xftfont caviar dreams:size=8 xftalpha 0.5 uppercase no default_color FFFFFF color1 DDDDDD color2 AAAAAA color3 888888 lua_load ~/conky/conky.lua lua_load ~/conky/clock_rings.lua lua_draw_hook_post main lua_draw_hook_pre widgets lua_draw_hook_pre clock_ringsТакже в конфиге conky мы установили имя окна и класс в контексте X11 системы, теперь можем проверить после запуска конки что окно имеет соответствующие атрибуты с помощью программ xprop или xwininfo
xprop
xwininfo -name conkyУбедившись что все в порядке идем в кофиг композитного менеджера и настраиваем там исключение теней для определенных окон с каким-либо классом. Файл:
vim ~/.compton.confКонфиг:
shadow = true; no-dock-shadow = true; no-dnd-shadow = true; clear-shadow = true; shadow-radius = 10; shadow-offset-x = -15; shadow-offset-y = -15; shadow-exclude = [ "n:e:Notification", "i:a:conky'" ]; shadow-ignore-shaped = true; menu-opacity = 1; inactive-opacity = 0.9; alpha-step = 0.06; blur-background-fixed = false; blur-background-exclude = [ "window_type = 'desktop'" ]; fading = false; backend = "xrender" mark-wmwin-focused = true; mark-ovredir-focused = true; use-ewmh-active-win = false; detect-rounded-corners = true; detect-client-opacity = true; refresh-rate = 0; vsync = "opengl"; dbe = false; paint-on-overlay = false; sw-opti = false; unredir-if-possible = false; focus-exclude = [ "n:a:conky'", "class_g = 'conky'" ]; detect-transient = true; detect-client-leader = true; invert-color-include = [ ]; glx-copy-from-front = false; glx-swap-method = "undefined"; wintypes: { override = { fade = false; shadow = false; opacity = 0.75; ocus = false; }; };Интересует нас строка:
shadow-exclude = [ "n:e:Notification", "i:a:conky'" ];Настройка других окон задается так:
condition = TARGET:TYPE[FLAGS]:PATTERN TARGET может принимать одно из значений: "n" (имя окна), "i" (конкретный класс окна), "g" (общий класс окна) и "r" (функции окна). TYPE может принимать одно из значений: "e" (точное совпадение) "a" (любое совпадение), "s" (совпадение сначала), "w" (шаблон) и "p" (регулярное выражение PCRE, если скомпилировано с поддержкой). FLAGS может быть набором параметров. На данный момент единственным установленным параметром является "i" (игнорировать регистр). PATTERN фактически является строкой шаблона.Теперь наш conky отображается без теней.
Потеря фокуса окнами при переключении awesome тагов (скринов X11):
Виноваты в этом настройки аттрибутов окон и расширение awesome autofocus.lua которое при переключении тага автоматически вешает фокус на последние приложение из истории фокуса.Сразу оговорюсь - как не старался я запретить фокус для окон conky и cairo-dock, при клике мышкой по ним они все равно получали фокус, поэтому для решения проблемы я выбрал следующую стратегию : не заносить в историю фокуса окна с классом conky & cairo-dock, чтобы не отвлекать на них хоткеи, а также реализовал хук (функция которая вызывается при определенном событии) а) при получении клиента фокуса и б) при условии что окна имеют нежелательный клас - отдавать фокус на последние приложение из истории фокуса если оно есть и таким же образом внес изменения в awesome autofocus.lua расширение - если фокус не выбран, брать из итории фокуса, исключая окна с определенными X11 классами. На заметку: awesome как и множество других c++\c приложений использует для гибкости конфигурации lua скриптовый язык, а именно при инициализации оконного менеджера запускает пользовательские скрипты написанные на языке lua и тем самым динамически формирует параметры окон, их поведение, хоткеи, инициализацию приложений, начальные параметры окон, позицию, размеры и многое другое.
Несколько полезных замечаний по lua:
- по аналогии с php die() - break служит для остановки скрипта
- в awesome для вывода уведомлений используется lua библиотека naughtify с помощью которой удобно дебажить в процессе проверки сценария (выводить данные в всплывающих окнах - когда что-то случается)
-
naughty.notify({ preset = naughty.config.presets.warning, title = "Oops", text = 'my text or some variable' })
Чтобы избежать ситуаций когда вы сломали скрипт (фатал) и у вас не запускается оконник и вам трудно найти в большом файле ошибку или тем более вы плохо знаете язык - лучше положить файл под систему контроля версий, можно воспользоваться к примеру бесплатным сервисом который поддерживает git и приватные репозитории https://bitbucket.org
vim /usr/share/awesome/lib/awful/client.luaДобавляем проверку на классы окон чтобы они не попадали в историю фокуса
--- Update client focus history. -- @param c The client that has been focused. function client.focus.history.add(c) if c.class ~= 'Cairo-dock' and c.class ~= 'cairo-dock' and c.class ~= 'conky' then -- Remove the client if its in stack client.focus.history.delete(c) -- Record the client has latest focused table.insert(client.data.focus, 1, c) end end
vim /usr/share/awesome/lib/awful/autofocus.luaДобавляем проверку на автоматический фокус, если окна имеют ненужный класс - берем более поздние приложения из истории. Для этого реализуем функцию:
-- Avoid conky & cairo-dock form focusing. function get_proper_client_for_focus(obj) local c = nil local i = 0 local c = {} local properClient = false -- Avoid conky & cairo-dock form focusing. while not properClient and i < 3 do c = aclient.focus.history.get(obj.screen, i) if c and c.class ~= 'Cairo-dock' and c.class ~= 'cairo-dock' and c.class ~= 'conky' then properClient = true end i = i + 1 end if c and not (c.class ~= 'Cairo-dock' and c.class ~= 'cairo-dock' and c.class ~= 'conky') then c = nil end return c endИ изменим функцию автофокуса для интеграции с нашей логикой:
--- When loaded, this module makes sure that there's always -- a client that will have focus -- on event such as tag switching, client unmanaging, etc. -- awful.autofocus -- Give focus when clients appear/disappear. -- @param obj An object that should have a .screen property. local function check_focus(obj) -- When no visible client has the focus... if not client.focus or not client.focus:isvisible() then local c = get_proper_client_for_focus(obj) if c and c.class ~= 'Cairo-dock' and c.class ~= 'cairo-dock' and c.class ~= 'conky' then client.focus = c end end endДальше идем в конфиг awesome пользователя
vim ~/.config/awesome/rc.luaИз спецификации оконного менеджера известно что он имеет настройку начальных параметров для запущенных приложений\окон по аналогии с каскадной таблицей стилей CSS в HTML языке.
Иными словами X11 окна имеют различные атрибуты, такие как класс, имя по ним строится селектор, а далее указывается как модифицировать свойства окна, а именно свойства X11 окон (размер, начальная позиция и т.д.) и некоторые built-in awesome свойства окон (floating, focusable, below и прочие)
Настройка параметров окон в awesome реализована посредством rules. В файле конфига есть (внизу) такая секция, для наших окон задаем правила
-- {{{ Rules awful.rules.rules = { -- All clients will match this rule. { rule = { }, properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, --focus = awful.client.focus.filter, keys = clientkeys, size_hints_honor = false, buttons = clientbuttons } }, { rule = {class = "cairo-dock" }, properties = { border_width = 0, border_color = 0, size_hints_honor = false, floating = true, focusable = false, modal = true, below = true } }, { rule = { class = "conky" }, properties = { border_width = 0, border_color = 0, size_hints_honor = false, floating = true, focusable = false, modal = true, width = 303, height = 450, below = true }, callback = function(c) local scr_area = screen[c.screen].workarea local cl_strut = c:struts() local geometry = nil c:geometry({ x = (scr_area.width - 285), y = 10, width = 305, height = 450, }) end } }Флаг floating позволяет на жестких layout'ах не мешать другим окнам нормально располагаться, focus - при инициализации выключен, focusable - не дает окну принимать фокус, у меня не получилось добиться корректной работы этого параметра.
Далее в этом же файле правим (если есть) или создаем новый хук реагирующий на получение окном фокуса:
client.connect_signal("focus", function(c) if c.class == 'conky' then if c.screen and awful.client.history then c = get_proper_client_for_focus(c) if c then awful.client.focus = c end end return end if c.class == 'cairo-dock' or c.class == 'Cairo-dock' then if c.screen and awful.client.history then c = get_proper_client_for_focus(c) if c then awful.client.focus = c end end return end c.border_color = beautiful.border_focus end)
Идем в хук который срабатывает при первичной инициализации приложения\окна и убираем логику которая фокусит окна если на них есть нежелательный класс:
-- {{{ Signals -- Signal function to execute when a new client appears. client.connect_signal("manage", function (c, startup) if c.class == 'cairo-dock' then return elseif c.class == 'conky' then return else client.focus = c client.focus:raise() end end)
Поблема начального позиционирования
Возможно вы уже заметили выше по тексту, rules секция, нужный код, который с помощью rule для awesome окна и lua функцией задает позицию, вот он:
rule = { class = "conky" }, properties = { border_width = 0, border_color = 0, size_hints_honor = false, floating = true, focusable = false, modal = true, width = 303, height = 450, below = true }, callback = function(c) local scr_area = screen[c.screen].workarea local cl_strut = c:struts() local geometry = nil c:geometry({ x = (scr_area.width - 285), y = 10, width = 305, height = 450, }) end }Здесь нет ничего сложного - при инициализации окна исполняется функция, в ней можно написать что угодно, мы в данном случае меняет отступы по x и y координатам, а также weight и height окна, в переменной scr_area содержатся данные о размере текущего sceen'a (расширение монитора).