Pull to refresh

Моё знакомство с WM Awesome. Часть 2

Desktop environments *
Продолжение моего т.н. знакомства с WM Awesome

Первая часть статьи тут.

Тут объявляем все виджеты, которые буду использоваться. Сразу стоит отметить баг — при нажатии клавиши «отключить звук» звук исчезает, при повторном нажатии — на виджете отображает, что звук включён, но его нету. Приходится прописывать команду вручную в консоли, странно. Пока не нашёл как его исправить. И ещё смущает отображаение громкости — 90% по факту ~70 единиц в alsamixer, надо бы исправить, но никак не дойдёт руки. Ну а остальное вроде как интуитивно понятно


Виджеты
---------------------
--- Виджеты ---
---------------------
opening_brace = '<span foreground="white" font_desc="Ubuntu">[</span>'
closing_brace = '<span foreground="white" font_desc="Ubuntu">] </span>'
function enbrace(str)
   return " "..opening_brace..str..closing_brace..' '
end

function colorify(str, color)
   return '<span foreground="'..color..'">'..str..'</span>'
end

function get_colorload(val)
   local color = 'green'
   if val > 85 then
      color = 'red'
   elseif val > 60 then
      color = 'yellow'
   end
   return color
end

function format_throughput(val)
   if (val < 1000) then
      return string.format('%3dKB/s', val)
   elseif (val < 10240) then
      return string.format('%.1fMB/s', val/1024)
   else
      return string.format('%3dMB/s', val/1024)
   end
end

one_sec_timer = timer{timeout = 1}
ten_sec_timer = timer{timeout = 10}

spacer_big = wibox.widget.textbox()
  spacer_big:set_text('     ')
spacer_small = wibox.widget.textbox()
  spacer_small:set_text('  ')
volumecfg = {}
volumecfg.cardid  = 0
volumecfg.channel = "Master"
volumecfg.widget = wibox.widget.textbox()
vol_color = {}
-- command must start with a space!
volumecfg.mixercommand = function (command)
       local fd = io.popen("amixer -c " .. volumecfg.cardid .. command)
       local status = fd:read("*all")
       fd:close()

       local volume = string.match(status, "(%d?%d?%d)%%")
       volume = string.format("% 3d", volume)
       status = string.match(status, "%[(o[^%]]*)%]")
       if string.find(status, "on", 1, true) then
               volume = volume .. "%"
	       vol_color="cyan"
       else
               volume = volume .. "×"
		vol_color = "red"
       end
       volumecfg.widget:set_markup(enbrace(colorify(volume, vol_color)))

end
volumecfg.update = function ()
       volumecfg.mixercommand(" sget " .. volumecfg.channel)
end
volumecfg.up = function ()
       volumecfg.mixercommand(" sset " .. volumecfg.channel .. " 1%+")
end
volumecfg.down = function ()
       volumecfg.mixercommand(" sset " .. volumecfg.channel .. " 1%-")
end
volumecfg.toggle = function ()
       volumecfg.mixercommand(" sset " .. volumecfg.channel .. " toggle")
end
volumecfg.update()

client.connect_signal("manage", function (c, startup)
    c.size_hints_honor = false
end)

batterybox = wibox.widget.textbox()

function battery ()
   local io_info = io.open("/proc/acpi/battery/BAT0/info")
   local io_state  = io.open("/proc/acpi/battery/BAT0/state")
   local str_info = io_info:read("*a")
   local str_state = io_state:read("*a")
   io.close(io_info)
   io.close(io_state)

   local capacity = str_info:match("last full capacity:%s+(%d+)")
   local current  = str_state:match("remaining capacity:%s+(%d+)")
   local state    = str_state:match("charging state:%s+(%a+)")
   local rate     = str_state:match("present rate:%s+(%d+)")

   local st_color = 'green'
   if state == 'discharging' then
      st_color = 'red'
   elseif state == 'charging' then
      st_color = 'yellow'
   end

   local remain_time_str = 'inf'
   remain_chrg = ((current * 100) / capacity)
   if (('discharging' == state) and (nil ~= rate) and (rate > '0')) then
      remain_time = current/rate
      remain_time_str = string.format('%dh %.2dm', remain_time, remain_time*60%60)
   end
   local rem_color = 'red'
   if remain_chrg > 15 then
      rem_color = 'yellow'
   end
   if remain_chrg > 60 then
      rem_color = 'green'
   end
   batterybox:set_markup( enbrace(colorify('bat: ', 'orange')
                           ..colorify(string.format("%d%%", remain_chrg), rem_color)
                           ..', '
                           ..colorify(remain_time_str, rem_color)
                           ..', '
                           ..colorify(state, st_color)))
end

battery()
ten_sec_timer:connect_signal("timeout", battery)


membox = wibox.widget.textbox()
function memory()
   local io_meminfo      = io.open("/proc/meminfo")
   local str_meminfo     = io_meminfo:read("*a")
   io.close(io_meminfo)

   local total           = str_meminfo:match("MemTotal:%s+(%d+)")
   local free            = str_meminfo:match("MemFree:%s+(%d+)")
   local buffers         = str_meminfo:match("Buffers:%s+(%d+)")
   local cached          = str_meminfo:match("Cached:%s+(%d+)")
   local swap_total      = str_meminfo:match("SwapTotal:%s+(%d+)")
   local swap_free       = str_meminfo:match("SwapFree:%s+(%d+)")
   local swap_cached     = str_meminfo:match("SwapCached:%s+(%d+)")

   local total_free      = free + buffers + cached
   local total_swap_free = swap_free + swap_cached

   local p_mem           = 100*(total - total_free)/total
   local mem_color       = get_colorload(p_mem)
   local sw_mem          = 100*(swap_total - total_swap_free)/swap_total
   local sw_mem_color    = get_colorload(sw_mem)

   local p_mem           = 100*(total - total_free)/total
   local mem_color       = get_colorload(p_mem)
   local sw_mem          = 100*(swap_total - total_swap_free)/swap_total
   local sw_mem_color    = get_colorload(sw_mem)

   membox:set_markup(enbrace(
                             colorify('mem: ', 'orange')
                             ..colorify(string.format('%2d%%', p_mem), mem_color)
                             ..'('..colorify(string.format('%3dMb', (total - total_free)/1024), mem_color)
                             ..colorify(string.format('/%3dMb', (total)/1024), 'white')
                             ..')'
                             ..' | '
                             ..colorify('swap: ', 'orange')
                             ..colorify(string.format('%2d%%', sw_mem), sw_mem_color)
                             ..'('..colorify(string.format('%3dMb', (swap_total - total_swap_free)/1024), sw_mem_color)
                             ..colorify(string.format('/%3dMb', (swap_total)/1024), 'white')
                             ..')'
                            )
                     )
end
memory()
one_sec_timer:connect_signal("timeout", memory)

-- CPU usage widget
cpugraph = awful.widget.graph()
cpugraph:set_width(75)
cpugraph:set_height(25)
cpugraph:set_background_color("#494B4F")
--cpugraph:set_color("#FF5656")
cpugraph:set_color({ type = "horisontal", from = { 0, 0 }, to = { 0, 20 }, stops = { { 0, "#FF5656" }, { 0.5, "#88A175" }, { 1, "#AECF96" } }})
-- Register CPU widget
vicious.register(cpugraph, vicious.widgets.cpu, 
                    function (widget, args)
                        return args[1]
                    end)
cpubox = wibox.widget.textbox()
cpubox_img = wibox.widget.imagebox()
cpu_arr = {}
cpu0_arr = {}
cpu1_arr = {}
for i = 0, 4 do
   cpu_arr[i] = 0
   cpu0_arr[i] = 0
   cpu1_arr[i] = 0
end
function parse_cpu(cpu, stat)
   local cpu_new = {}
   local ret = {}
   cpu_new[0], cpu_new[1], cpu_new[2], cpu_new[3], cpu_new[4] = stat:match("cpu%d*%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)")

   local idle   = (cpu_new[3] - cpu[3]) + (cpu_new[4] - cpu[4])
   local user   = (cpu_new[1] - cpu[1]) + (cpu_new[0] - cpu[0])
   local system = (cpu_new[2] - cpu[2])
   local total  = idle + user + system
   local busy   = user + system

   ret['busy'] = busy*100/total
   ret['sys'] = system*100/total
   ret['user'] = user*100/total
   ret['cpu'] = cpu_new

   return ret
end

function cpu()
   local io_stat  = io.open("/proc/stat")
   local str_stat = io_stat:read("*l")
   io.close(io_stat)

   local ret = parse_cpu(cpu_arr, str_stat)
   cpu_arr = ret['cpu']



   cpubox:set_markup (enbrace(colorify('cpu: ', 'orange')
                       ..'('
                       ..colorify(string.format('%3d%%', ret['busy']), get_colorload(ret['busy']))
                       ..') | (u:'
                       ..colorify(string.format('%3d%%', ret['user']), get_colorload(ret['user']))
                       ..', s:'
                       ..colorify(string.format('%3d%%', ret['sys']), get_colorload(ret['sys']))
                       ..')'))
end

cpu()
one_sec_timer:connect_signal("timeout", cpu)

		    
hddbox = wibox.widget.textbox()
hdd_r = 0
hdd_w = 0
hddlist = {'/sys/block/sda/stat', '/sys/block/sdb/stat'}

function hdd()
   local new_r = 0
   local new_w = 0
   for i = 1, 2 do
      local io_stat = io.open(hddlist[i])
      local str_stat = io_stat:read("*a")
      io.close(io_stat)
      local rd, wr = str_stat:match("%s+%d+%s+%d+%s+(%d+)%s+%d+%s+%d+%s+%d+%s+(%d+)")
      new_w = new_w + wr
      new_r = new_r + rd
   end
   local r = (new_r - hdd_r)/2
   local w = (new_w - hdd_w)/2
   hdd_w = new_w
   hdd_r = new_r

   hddbox:set_markup ( enbrace(colorify('i/o: ', 'orange')
                       ..'(r: '
                       ..colorify(format_throughput(r), 'green')
                       ..', w:'
                       ..colorify(format_throughput(w), 'green')
                       ..')'))
end
-- RAM usage widget
memwidget = awful.widget.progressbar()
memwidget:set_width(30)
memwidget:set_height(25)
memwidget:set_vertical(true)
memwidget:set_background_color('#494B4F')
memwidget:set_color('#AECF96')
cpugraph:set_color({ type = "linear", from = { 0, 0 }, to = { 0, 20 }, stops = { { 0, "#AECF96" }, { 0.5, "#88A175" }, { 1, "#FF5656" } }})

vicious.cache(vicious.widgets.mem)
vicious.register(memwidget, vicious.widgets.mem,
                function (widget, args)
                    return args[1]
                 end, 1)
                 --update every 13 seconds

hdd()
one_sec_timer:connect_signal("timeout", hdd)


-- Start timers to update widgets
one_sec_timer:start()
ten_sec_timer:start()
-- Часы и дата
text_clock = awful.widget.textclock()
-- Create a systray
systray = wibox.widget.systray()



Знаю, что верхнюю и нижнюю панель можно было создать вместе, а не разделять, и так наверное было бы даже грамотнее, но у меня руки не доходят переписать. Собственно в этой части мы создаём теги и отображаем виджеты.
Панели
--------------------------------------------------
--- Декларируем список тэгов #1 ---
--------------------------------------------------
main_wibox = {}
prompt_box = {}
layout_box = {}
tag_list = {}
-- Задаем обработку кнопок мыши для списка тегов
tag_list.buttons = awful.util.table.join(
                 -- Отобразить тэг
                 awful.button({ }, left_button, awful.tag.viewonly ),
                 -- Переместить клиент на данный тэг
                 awful.button({ modkey }, left_button, awful.client.movetotag ),
                 -- Отобразить выбранный тэг вместе с текущим
                 awful.button({ }, right_button, awful.tag.viewtoggle ),
                 -- Отобразить текущий клиент в текущем и выбранном тэге
                 awful.button({ modkey }, right_button, awful.client.toggletag ),
                 -- Следующий тэг
                 awful.button({ }, plus_button, function(t) awful.tag.viewnext(awful.tag.getscreen(t)) end ),
                 -- Предыдущий тэг
                 awful.button({ }, minus_button, function(t) awful.tag.viewprev(awful.tag.getscreen(t)) end )
)
---------------------------------------------------
--- Декларируем список задач #1 ---
---------------------------------------------------
-- Задаем обработку кнопок мыши для списка задач
task_list = {}
task_list.buttons = awful.util.table.join(
                  -- Левая кнопка
                  awful.button({ }, left_button, function(c)
                               -- Если клиент имеет фокус - свернуть его
                               if c == client.focus then
                                  c.minimized = true
                               else -- Иначе, передать фокус на клиент не сворачивая
                                  c.minimized = false
                                   -- и ещё вот эта хрень, назначение которой мне пока не ясно
                                  if not c:isvisible() then
	                             awful.tag.viewonly(c:tags()[1])
                                  end
                                  client.focus = c
                                  c:raise()
                               end
                  end),
                  -- Щелчок правой кнопкой
                  awful.button({ }, right_button, function(c)
                               if instance then
                                  instance:hide()
                                  instance = nil
                               else
                                  instance = awful.menu.clients({ width=250 })
                               end
                  end),
                  -- Сместить фокус на следующее окно
                  awful.button({ }, plus_button, function ()
                               awful.client.focus.byidx(1)
                               if client.focus then 
                                  client.focus:raise()
                               end
                  end),
                  -- Сместить фокус на предыдущее окно
                  awful.button({ }, minus_button, function()
                               awful.client.focus.byidx(-1)
                               if client.focus then 
                                  client.focus:raise()
                               end
                  end)
)

--------------------------------------------------------------------------
--- Создаем для каждого экрана панель задач #1 ---
---------------------------------------------------------------------------
-- Цикл, перебирающий все экраны
for s = 1, screen.count() do
  -- Список тэгов: передаем номер экрана, и назначения кнопок мыши
  tag_list[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, tag_list.buttons)
  -- Список запущенных задач: передаем номер экрана, и назначения кнопок мыши
  task_list[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, task_list.buttons)
  -- Контейнер для всех виджетов - наша панель задач
  -- расположенная внизу экрана номер s и шириной
  main_wibox[s] = awful.wibox({ position = "top", height = "28", screen = s })
  -- Создаем виджеты расположенные слева  (левый блок виджетов)
  local left_layout = wibox.layout.fixed.horizontal()
  -- Добавляем на левый блок виджетов последовательно
  left_layout:add(launcher) -- лаунчер (кнопка главного меню)
  left_layout:add(tag_list[s]) -- список тэгов
  -- Создаем виджеты расположенные справа
  local right_layout = wibox.layout.fixed.horizontal()
  -- Системный трей делаем почему-то только на первом экране, взято из стандартного конфига
  if s == 1 then right_layout:add(wibox.widget.systray()) end
  -- Добавляем
  right_layout:add(volumecfg.widget)
  right_layout:add(text_clock) -- Текстовые часы
  -- Создаем контейнер для всей панели задач
  local layout = wibox.layout.align.horizontal()
  layout:set_left(left_layout)
  layout:set_middle(task_list[s])
  layout:set_right(right_layout)
  main_wibox[s]:set_widget(layout)
end

--------------------------------------------------
--- Декларируем список тэгов #2 ---
--------------------------------------------------
bottom_wibox = {}
bottom_prompt_box = {}
botton_layout_box = {}

---------------------------------------------------------------------------
--- Создаем для каждого экрана панель задач #2 ---
---------------------------------------------------------------------------
-- Цикл, перебирающий все экраны
for s = 1, screen.count() do
-- Кнопка переключения макетов расположения окон
layout_box[s] = awful.widget.layoutbox(s)
-- декларируем для неё назначения кнопок мыши
layout_box[s]:buttons(awful.util.table.join(
       -- Переключить на макет вперед
       awful.button({ }, left_button, function () awful.layout.inc(layouts, 1) end),
       -- Переключить на макет назад 
       awful.button({ }, right_button, function () awful.layout.inc(layouts, -1) end)
  )
)
  -- Командная строка - виджет реализующий командную строку на панели задач
bottom_prompt_box[s] = awful.widget.prompt()
  -- Контейнер для всех виджетов - наша панель задач
  -- расположенная внизу экрана номер s и шириной в px
bottom_wibox[s] = awful.wibox({ position = "bottom", height = "25", screen = s })
  -- Создаем виджеты расположенные слева  (левый блок виджетов)
local l_layout = wibox.layout.fixed.horizontal()
  -- Добавляем на левый блок виджетов последовательно
l_layout:add(bottom_prompt_box[s]) -- командную строку
l_layout:add(spacer_small)         -- otstup
l_layout:add(cpubox)
l_layout:add(cpugraph)
l_layout:add(spacer_small)
l_layout:add(membox)
l_layout:add(memwidget)
  -- Создаем виджеты расположенные справа
local r_layout = wibox.layout.fixed.horizontal()
r_layout:add(hddbox)
r_layout:add(spacer_small)
r_layout:add(batterybox)
r_layout:add(spacer_small)
r_layout:add(layout_box[s]) -- Кнопку переключения макетов
  -- Создаем контейнер для всей панели задач
local lay = wibox.layout.align.horizontal()
lay:set_left(l_layout)
--lay:set_middle()
lay:set_right(r_layout)
bottom_wibox[s]:set_widget(lay)
end



Третья часть здесь
Tags:
Hubs:
Total votes 15: ↑6 and ↓9 -3
Views 13K
Comments Comments 2