Анатомия Awesome WM

serkhay
Ну и зачем вам так часто обновлять часы?) Мои текстовые часы обновляются раз в 31 секунду, awesome почти процессора не жрет

Стрелка секундная идет
Да пребудет с нами Сила...!
CPU Intel Core i7 2600K/RAM DDR3 16 Gb/NVidia GForce 580GTX/HDD Seagate SATA3 2 Tb
http://maisvendoo.org
maisvendoo
P.S.: Как бы это все теперь в отдельный модуль засунуть. Кода много уже слишком для rc.lua
Создаете рядом с rc.lua файл с именем, например, conky.lua, а в самом rc.lua пишете require ("conky")
maisvendoo
Стрелка секундная идет
А почему бы ее не обновлять раз в секунду, а не в 0.1 секунды?)

Да я понимаю, это все красиво, но все эти красивости только процессор жрут, хотя вам наверное это не так важно)
serkhay
А почему бы ее не обновлять раз в секунду, а не в 0.1 секунды?)
Да я понимаю, это все красиво, но все эти красивости только процессор жрут, хотя вам наверное это не так важно)

Интервал обновления в обновления в 1 секунду сильно не уменьшает потребление ресурсов. Вернее вообще не уменьшает.

serkhay
хотя вам наверное это не так важно)

Беда современной компьютерной индустрии, в частности игровой - ориентация на мощное железо, без оглядки на оптимизацию кода. Канеш оптимизация денег стоит, тем не менее можно накрутить такого что и intel core i7 почувствует :)

serkhay
Создаете рядом с rc.lua файл с именем, например, conky.lua, а в самом rc.lua пишете require ("conky")

Спасибо, сделал так

P.S.: Ну вот, виджеты, сделаные на связке lua + conky заменены на соответствующие по функционалу awesome-виджеты. Теперь надо написать заметку о том как и что делалось поподробнее
Да пребудет с нами Сила...!
CPU Intel Core i7 2600K/RAM DDR3 16 Gb/NVidia GForce 580GTX/HDD Seagate SATA3 2 Tb
http://maisvendoo.org
Awesome WM: анимированный виджет на рабочем столе: аналоговые часы

Итак, из содержания топика вполне понятна следующая проблема, которую необходимо обсудить.

Проблема состояла в том, что уж очень хотелось реализовать часики, успешно работавшие у меня ещё в Openbox-е, но не с помощью связки conky + lua, а используя лишь Lua и средства, предоставляемые самим Awesome. Как оказалось, задача вполне решаемая, тому есть многочисленные примеры

Однако авторы примеров скромно отмалчиваются от подробностей реализации. Ссылки приведенные на ЛОРе, а так же проницательность serkhay помогли написать этот небольшой гайд.

1. Создаем wibox

Нам необходим контейнер для виджетов, который спокойненько размещался бы на рабочем столе, не перекрывал и не сдвигал бы другие окна. С помощью serkhay удалось установить что для создания такого wibox необходитмо использовать модуль wibox, а не awful.wibox, как это делается при создании главной панели awesome. Достаточно такого кода


local wibox = require("wibox")

-------------------------------------------------------------------------------
--	Параметры часов
-------------------------------------------------------------------------------
clock.width = 300		-- ширина
clock.height = 300		-- высота
clock.bg_color = "#00000000"	-- цвет фона

clock.x = 20			-- Координаты
clock.y = 20			-- левого верхнего угла

-------------------------------------------------------------------------------
--	Создаем wibox
-------------------------------------------------------------------------------
local clock_wbox = wibox({ bg = clock.bg_color,
                           width = clock.width,
			   height = clock.height})

clock_wbox.ontop = false			-- Ниже всех окон
clock_wbox.visible = true			-- Виден
clock_wbox:geometry({x = clock.x, y = clock.y})	-- Координаты
для реализации задуманного

2. Использование cairo в виджетах

Для рисования в conky использовалась библиотека cairo, тот же подход необходимо было реализовать и тут, хотя бы для того чтобы быстро перенести уже имеющийся код часиков. Как оказалось, в Awe-вики довольно доходчиво и с примером объяснена методика скрещивания виджета с cairo.

Для начала необходим специальный виджет

-------------------------------------------------------------------------------
--	Создаем виджет
-------------------------------------------------------------------------------
local clock_widget = wibox.widget.base.make_widget()

Этот виджет должен иметь две функции, как я понял они являюются функциями обратного вызова (callback)

Первая, fit(widget, width, height) позволяет определить размеры виджета, в вики об этом как-то путанно написано, я сделал у себя так

-------------------------------------------------------------------------------
--	Функция, определяющая размеры виджета
-------------------------------------------------------------------------------
clock_widget.fit = function(clock_widget, width, height)

  return width, height

end

Вторая, draw(widget, wibox, cr, width, height), выполняет собственно отрисовку часов

clock_widget.draw = function(clock_widget, clock_wbox, cr, width, height)

-- Здесь рисуем часы
-- подробно это описывать не буду, приложу исходник

end

Обе callback-функции обязательно должны присутствовать. Собственно в функцию draw awesome передает контекст рисования cairo в виде параметра cr, от которого и пляшет отрисовка



-- Определяем характерные размеры, относительно текущей ширины виджета
  local radius = width/2 - 5
  local cx = width/2
  local cy = height/2

  local hour_len = 15
  local min_len = 7

  -- Рисуем циферблат

  -- Рисуем часовые деления
  cr:set_line_width (2)
  cr:set_source_rgba (0.7, 0.7, 0.7, 1)

  for i = 0,11 do

	cr:move_to (cx + (radius - hour_len)*math.sin(i*math.rad(30)), cy - (radius - hour_len)*math.cos(i*math.rad(30)) )
	cr:line_to (cx + radius*math.sin(i*math.rad(30)), cy - radius*math.cos(i*math.rad(30)) )
	cr:stroke ()

  end

--.
--.
--.
-- И так далее, рисуем себе...

3. Размещаем виджет на экране

Виджет добавляем в wibox, созданный нами заранее


-------------------------------------------------------------------------------
--	Размещаем виджет
-------------------------------------------------------------------------------
local clock_layout = wibox.layout.fixed.horizontal()

clock_layout:add(clock_widget)

clock_wbox:set_widget(clock_layout)

4. "А почему они стоят на месте???!!!"

А потому, что мы не сказали нашему WM с какой частотой обновлять изображение часов. Для периодического обновления виджета надо создать таймер. Методика, кстати подсмотрена в /usr/share/awesome/lib/awful/widget/textclock.lua


local capi = {timer = timer}

-------------------------------------------------------------------------------
--	Анимация
-------------------------------------------------------------------------------

-- Делаем таймер с интервалом в 100 мс
local timer = capi.timer{timeout = 0.1}

Связываем с ним вызов функции перерисовки wibox


-- Вешаем на таймер отрисовку wibox
timer:connect_signal("timeout", function() clock_wbox.draw() end)

Запускаем таймер

-- Запускаем таймер
timer:start()

-- Заставляем таймер генерировать сигнал timeout
timer:emit_signal("timeout")

После добавления такого кода часы начнут тикать :)

Заключение

Полный исходник сабжа clock.lua

Результат вот :)


Успехов Вам!

P.S.: Огромное спасибо serkhay за помощь при создании гайда :)
Да пребудет с нами Сила...!
CPU Intel Core i7 2600K/RAM DDR3 16 Gb/NVidia GForce 580GTX/HDD Seagate SATA3 2 Tb
http://maisvendoo.org
maisvendoo, сделайте в стартовом сообщении что-то типа оглавления (название+ссылка), чтоб ваши хаутушки не терялись среди обсуждений.
vadik
maisvendoo, сделайте в стартовом сообщении что-то типа оглавления...

Сделал, хорошая идея.

Вообще слегка откорректирвал структуру треда
Да пребудет с нами Сила...!
CPU Intel Core i7 2600K/RAM DDR3 16 Gb/NVidia GForce 580GTX/HDD Seagate SATA3 2 Tb
http://maisvendoo.org
Поскольку заметок прибавилось, вперемешку с обсуждением их, решено навести порядок в блоге. Пост про автозагрузку перенесен вниз, вместо него добавлено ОГЛАВЛЕНИЕ

Список автозагрузки средствами Awesome

Те кто пользуются Awesome WM наверняка знают о существующей в нем возможности быстрого перезапуска графической оболочки, при изменении настроек в rc.lua, без закрытия открытых в данный момент окон. Что и говорить, удобная фишка, особенно при наладке awesome и, особенно, для новичков.

Возникает, однако проблема с приложениями стоящими в автозагрузке - если не принимать специальных мер, при перезапуске среды они будут продублированны, что может привести к разным непредсказуемым вещам, да и просто неприятно и неудобно.

Выходит так из-за того, что автозагрузка в awesome реализована в том же самом скрипте rc.lua, который отправляется на выполнения при старте/рестарте WM.

Гугление дает несколько вариантов решения данной проблемы, главный из которых - написание скрипта run_once.sh


#! /bin/bash

if [ ! "`ps -A | grep $1`" ]; then
  $@;
fi

который грепает вывод команды ps c целью поиска уже запущенного процесса и в случае нахождения оного не запускает новую копию. Выполняемая команда передается ему в качестве параметра.

Какой недостаток в данном подходе? А если необходимо реализовать в автозапуске что-то подобное скриншоту



три одинаковых терминала через такой run_once.sh уже не запустить, то есть скрипт надо существенно модифицировать.

Поэтому было принято решение реализовать все средствами Lua прямо в скрипте rc.lua

Для начала был создан файл ~/.config/awesome/autostart.lst такого вида

compton
urxvt -e mc
urxvt -e htop
urxvt
guake
sbxkb
conky -c ~/.conky/.conkyrc
conky -c ~/.conky/.conkyrc_lua_clock
conky -c ~/.conky/.conkyrc_updates

Это - команды, предназначенные для автозапуска.

Далее, где-нибудь в начале скрипта rc.lua пишем такое

-------------------------------------------------------------------------------
--	Формируем список автозапуска
-------------------------------------------------------------------------------
local autostart_list = {}

-- Открываем файл списка для чтения
local f = io.open("/home/maisvendoo/.config/awesome/autostart.lst", "r")

-- Число прочитанных команд
local num_cmd = 0

-- Читаем команды в список и считаем их
for line in f:lines() do

  autostart_list[num_cmd] = line
  num_cmd = num_cmd + 1

end

Теперь можно реализовать автозагрузку, например так

------------------------------------------------------------------------------
--	Автозапуск (этот код ставим в конце rc.lua)
------------------------------------------------------------------------------

-- Перебираем список автозапуска и стратуем всё с паузой в три секунды
for i = 0, num_cmd - 1 do

  awful.util.spawn_with_shell(autostart_list[i] .. " && sleep 3")

end

И, самое главное - действия при перезапуске awesome, у меня висящие на Mod4 + Ctrl + R

awful.key( { modkey,	"Control"	}, "#27",

  function()

    -- Грохаем весь автозапуск
    for i = 0, num_cmd - 1 do

      -- Ищем в команде первое слово - наверняка имя процесса,
      -- который надо убить
      local cmd = string.match(autostart_list[i], "%a+")

      -- Убиваем этот процесс
      awful.util.spawn_with_shell("killall " .. cmd)

    end

    -- Перезапускаем awesome
    awful.util.restart()

  end )

Теперь, чтобы добавить/убрать команду в список автозапуска достаточно отредактировать файл autostart.lst, не заботясь о действиях awesome по корректной обработке этих команд.
Да пребудет с нами Сила...!
CPU Intel Core i7 2600K/RAM DDR3 16 Gb/NVidia GForce 580GTX/HDD Seagate SATA3 2 Tb
http://maisvendoo.org
maisvendoo
три одинаковых терминала через такой run_once.sh уже не запустить, то есть скрипт надо существенно модифицировать.
Почему это? Попробовал - в rc.lua:
awful.util.spawn_with_shell("run_once urxvt -e htop")
awful.util.spawn_with_shell("run_once urxvt -e mc")
awful.util.spawn_with_shell("run_once urxvt")
Все три запускаются.
valera_cr
awful.util.spawn_with_shell("run_once urxvt -e htop")
awful.util.spawn_with_shell("run_once urxvt -e mc")
awful.util.spawn_with_shell("run_once urxvt")
Все три запускаются.

У меня последний не стартует почему-то
Да пребудет с нами Сила...!
CPU Intel Core i7 2600K/RAM DDR3 16 Gb/NVidia GForce 580GTX/HDD Seagate SATA3 2 Tb
http://maisvendoo.org
 
Зарегистрируйтесь или войдите что-бы оставить сообщение.