Drop-down terminal/ru

Введение
Выпадающий терминал всплывает из верхней части экрана, как в консолях видеоигр и может переключаться с помьщью одной клавиши. Приложения, такие как Yakuake, Guake или Tilda обеспечивают функциональность выпадающего терминала для обычных окружений рабочего стола. Тем не менее, в awesome и мощью lua, мы можем имитировать эту функциональность и при этом использовать наши обычные терминальные приложения.

Добавьте следующую функцию в ваш rc.lua и вызовите ее назначенной клавишей, что создаст новое окно для выпадающего(drop-down) терминала, если он еще не существует, или переключит его между скрытием и отображением, если он уже существует. Первым аргументом является запускаемая программа (например "urxvtc"), вторым агрументом является высота (в абсолютных пикселях, при значении >1 или проценте если <1, например 0.2 (20% высота экрана по умолчанию), и третьим агрументом служит номер экрана(screen). Второй аргумент является опциональным(не обязательным).

Функция
-- Данная функция для awesome версии <= 3.4

dropdown = {}

function dropdown_toggle(prog, height, s)  if s == nil then s = mouse.screen end if height == nil then height = 0.2 end if not dropdown[prog] then -- Create table dropdown[prog] = {} -- Add unmanage hook for dropdown programs awful.hooks.unmanage.register(function (c)                                      for scr, cl in pairs(dropdown[prog]) do                                          if cl == c then                                             dropdown[prog][scr] = nil                                          end                                       end                                    end) end if not dropdown[prog][s] then spawnw = function (c) -- Store client dropdown[prog][s] = c                 -- Float client awful.client.floating.set(c, true) -- Get screen geometry screengeom = screen[s].workarea -- Calculate height if height < 1 then height = screengeom.height*height end

-- I like a different border with for the popup window -- So I don't confuse it with terminals in the layout bw = 2

-- Resize client c:geometry({                               x = screengeom.x,                                y = screengeom.y - 1000,                                width = screengeom.width - bw,                                 height = height - bw                             })

-- Mark terminal as ontop --           c.ontop = true --           c.above = true c.border_width = bw

-- Focus and raise client c:raise client.focus = c

-- Remove hook awful.hooks.manage.unregister(spawnw) end

-- Add hook awful.hooks.manage.register(spawnw)

-- Spawn program awful.util.spawn(prog)

dropdown.currtag = awful.tag.selected(s) else -- Get client c = dropdown[prog][s] -- Switch the client to the current workspace

-- Focus and raise if not hidden if c.hidden then awful.client.movetotag(awful.tag.selected(s), c)        c.hidden = false c:raise client.focus = c     else if awful.tag.selected(s) == dropdown.currtag then c.hidden = true local ctags = c:tags for i, t in pairs(ctags) do              ctags[i] = nil end c:tags(ctags) else awful.client.movetotag(awful.tag.selected(s), c)           c:raise client.focus = c        end end dropdown.currtag = awful.tag.selected(s) end end

Scratch
Scratch обеспечивает выпадающие приложения и менеджер scratchpad manager для оконного менеджера awesome. Его модуль scratch.drop основан на коде описанном выше и совместим с awesome v3.4(сейчас также и с 3.5). Для большей информации, смотрите страницу Scratchpad manager.

Другие решения
Следующий код требует Lua 5.2 и Awesome 3.5 Предыдущее решение имеет два маленьких недостатка: консольное окно определяется как первое окно, и управляется только после первого запроса. Это может привести к состоянию первенства, но это маловероятно. Второй недостаток проявляется при перезапуске awesome, выпадающий терминал, перестает быть таким. Вместо этого появляется один липкий терминал. Это несколько неправильно. Поэтому далее приведено другое решение, которое работает через зависимость от присвоенного терминалу имени:

-- Quake like console on top -- Similar to: --  http://git.sysphere.org/awesome-configs/tree/scratch/drop.lua

-- But uses a different implementation. The main difference is that we -- are able to detect the Quake console from its name -- (QuakeConsoleNeedsUniqueName by default).

-- Use:

-- local quake = require("quake") -- local quakeconsole = {} -- for s = 1, screen.count do --   quakeconsole[s] = quake({ terminal = config.terminal, -- 			        height = 0.3, --                              screen = s }) -- end

-- config.keys.global = awful.util.table.join( --   config.keys.global, --    awful.key({ modkey }, "`", -- 	    function  quakeconsole[mouse.screen]:toggle end)

-- If you have a rule like "awful.client.setslave" for your terminals, -- ensure you use an exception for -- QuakeConsoleNeedsUniqueName. Otherwise, you may run into problems -- with focus.

local setmetatable = setmetatable local string = string local awful = require("awful") local capi  = { mouse = mouse, screen = screen, client = client, timer = timer }

-- I use a namespace for my modules... module("quake")

local QuakeConsole = {}

-- Display function QuakeConsole:display -- First, we locate the terminal local client = nil local i = 0 for c in awful.client.iterate(function (c)				 -- c.name may be changed!				  return c.instance == self.name			       end,			       nil, self.screen) do      i = i + 1 if i == 1 then client = c     else -- Additional matching clients, let's remove the sticky bit -- which may persist between awesome restarts. We don't close -- them as they may be valuable. They will just turn into a	 -- classic terminal. c.sticky = false c.ontop = false c.above = false end end

if not client and not self.visible then -- The terminal is not here yet but we don't want it yet. Just do nothing. return end

if not client then -- The client does not exist, we spawn it     awful.util.spawn(self.terminal .. " " .. string.format(self.argname, self.name),		       false, self.screen) return end

-- Comptute size local geom = capi.screen[self.screen].workarea local width, height = self.width, self.height if width <= 1 then width = geom.width * width end if height <= 1 then height = geom.height * height end local x, y  if     self.horiz == "left"  then x = geom.x   elseif self.horiz == "right" then x = geom.width + geom.x - width else  x = geom.x + (geom.width - width)/2 end if    self.vert == "top"    then y = geom.y   elseif self.vert == "bottom" then y = geom.height + geom.y - height else  y = geom.y + (geom.height - height)/2 end

-- Resize awful.client.floating.set(client, true) client.border_width = 0 client.size_hints_honor = false client:geometry({ x = x, y = y, width = width, height = height })

-- Sticky and on top client.ontop = true client.above = true client.skip_taskbar = true client.sticky = true

-- This is not a normal window, don't apply any specific keyboard stuff client:buttons({}) client:keys({})

-- Toggle display if self.visible then client.hidden = false client:raise capi.client.focus = client else client.hidden = true end end

-- Create a console function QuakeConsole:new(config) -- The "console" object is just its configuration.

-- The application to be invoked is: --  config.terminal .. " " .. string.format(config.argname, config.name) config.terminal = config.terminal or "xterm" -- application to spawn config.name    = config.name     or "QuakeConsoleNeedsUniqueName" -- window name config.argname = config.argname  or "-name %s"     -- how to specify window name

-- If width or height <= 1 this is a proportion of the workspace config.height  = config.height   or 0.25	       -- height config.width   = config.width    or 1	       -- width config.vert    = config.vert     or "top"	       -- top, bottom or center config.horiz   = config.horiz    or "center"       -- left, right or center

config.screen  = config.screen or capi.mouse.screen config.visible = config.visible or false -- Initially, not visible

local console = setmetatable(config, { __index = QuakeConsole }) capi.client.connect_signal("manage",			 function(c)			     if c.instance == console.name and c.screen == console.screen then				console:display			     end			  end) capi.client.connect_signal("unmanage",			 function(c)			     if c.instance == console.name and c.screen == console.screen then				console.visible = false			     end			  end)

-- "Reattach" currently running QuakeConsole. This is in case awesome is restarted. local reattach = capi.timer { timeout = 0 } reattach:connect_signal("timeout",		      function			  reattach:stop			  console:display		       end) reattach:start return console end

-- Toggle the console function QuakeConsole:toggle self.visible = not self.visible self:display end

setmetatable(_M, { __call = function(_, ...) return QuakeConsole:new(...) end })

Вышеописанный код будет работать с прилоежниями которые понимают присвоенные через терминал названия (xterm, rxvt). Пример использования:

local quake = require("quake")

local quakeconsole = {} for s = 1, screen.count do  quakeconsole[s] = quake({ terminal = config.terminal,			     height = 0.3,			     screen = s }) end

config.keys.global = awful.util.table.join(  config.keys.global,   awful.key({ modkey }, "`", function quakeconsole[mouse.screen]:toggle end)