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:

Оглавление


Тени от композитника:
В  конфигурационном файле 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 (расширение монитора).

 

Comments:

VOVANCHEG
КТО УДАЛИЛ МОЙ КОМЕНТ?!
30 окт 2013 в 21:54
аноним
By dealing together, two of you can address problems of self-esteem and mutual trust. He is content, as well as the opposite of our thoughts later years has in store for us.
19 авг 2017 в 01:31

add comment