Потрясающая альтернатива клавиатурному захвату WM (v3.5.5)

Мне никогда не нравились возможности переключения окон по умолчанию в Awesome, поэтому я решил реализовать поведение Alt-Tab, которое учитывает историю (и создает необычные эффекты непрозрачности).

При нажатии Alt-Tab вся история записывается в таблицу, и к этой истории добавляются свернутые окна (в том же теге). Когда эта таблица создается, я создаю экземпляр keygrabber, который фиксирует события нажатия Tab (для переключения на следующего клиента в таблице) и события Alt-release (для полного прерывания).

Флаг отслеживает, находится ли пользователь в процессе Alt-tabbing, чтобы таблица не создавалась снова и снова.

Код (его много, и вам, вероятно, не нужно его видеть, но мой опыт подсказывает мне, что, когда я не публикую весь код, люди в конечном итоге его попросят):

altTabbing = false
altTabIndex = 1
altTabHistory = {}
clientOpacities = {}

function altTabSetOpacities(restore)
   for i,c in pairs(altTabHistory) do
      if not restore and i ~= altTabIndex then
         c.opacity = 0.5
      else
         c.opacity = clientOpacities[i]
      end
   end
end

function myAltTab()
   -- First check if the user is already alttabbing, in which case the history
   -- should NOT be updated. If the user has just pressed alt-tab, generate a new 
   -- history-table

   if not altTabbing then -- generate history-table

      -- Clear Tables
      for i in pairs(altTabHistory) do altTabHistory[i] = nil end
      for i in pairs(clientOpacities) do clientOpacities[i] = nil end

      -- Get focus history for current tag
      local s = mouse.screen;
      local idx = 0
      local c = awful.client.focus.history.get(s, idx)

      while c do
         table.insert(altTabHistory, c)
         table.insert(clientOpacities, c.opacity)

         idx = idx + 1
         c = awful.client.focus.history.get(s, idx)
      end

      -- Minimized clients will not appear in the focus history
      -- Find them by cycling through all clients, and adding them to the list
      -- if not already there.
      -- This will preserve the history AND enable you to focus on minimized clients

      local t = awful.tag.selected(s)
      local all = client.get(s)

      for i = 1, #all do
         local c = all[i]
         local ctags = c:tags();

         -- check if the client is on the current tag
         local isCurrentTag = false
         for j = 1, #ctags do
            if t == ctags[j] then
               isCurrentTag = true
               break
            end
         end

         if isCurrentTag then
            -- check if client is already in the history
            -- if not, add it
            local addToHistory = true
            for k = 1, #altTabHistory do
               if altTabHistory[k] == c then
                  addToHistory = false
                  break
               end
            end

            if addToHistory then
               table.insert(altTabHistory, c)
               table.insert(clientOpacities, c.opacity)
            end
         end
      end

      -- reset current index and flag
      altTabIndex = 1
      altTabbing = true

      -- Now that we have collected all windows, we should run a keygrabber
      -- as long as the user is alt-tabbing:
      keygrabber.run(
         function (mod, key, event)  
            -- Stop alt-tabbing when the alt-key is released
            if key == "Alt_L" and event == "release" then
               altTabbing = false
               altTabSetOpacities(true)
               c = altTabHistory[altTabIndex]
               client.focus = c                  
               c:raise()   
               return false -- stop keygrabber
            end

            -- Move to next client on each Tab-press
            if key == "Tab" and event == "press" then
               myAltTab()
               return true -- keep going
            end

            return true -- keep going
         end
      )

   end -- if not altTabbing

   -- at this point, the user is alt-tabbing, so we should raise
   -- the next client in the history-table
   if #altTabHistory < 2 then return end

   -- Switch to next client
   altTabIndex = altTabIndex + 1
   if altTabIndex > #altTabHistory then
      altTabIndex = 1 -- wrap around
   end

   -- focus on current client
   local c = altTabHistory[altTabIndex]
   c.minimized = false
   c:raise()

   -- make current client stand out
   altTabSetOpacities(false)
end

Я понимаю, что кода много, но главное - это клавиатурный захват. По еще неизвестным причинам Awesome иногда дает сбой, когда я использую этот подход при нажатой клавише Alt. Я хочу заменить клавиатурный захват, подключив сигналы к клавишам Alt и Tab и отключив их, как только пользователь закончит. Однако по какой-то причине я не могу этого сделать.

Я создаю новый ключевой объект следующим образом:

local altkey = awful.key({}, "Alt_L")[1]

Методом проб и ошибок я обнаружил, что awful.key() фактически возвращает таблицу, из которой я могу запросить первый элемент для key, keysym и т. Д., Следовательно, [1]. Однако, когда я пытаюсь подключить сигнал к этому объекту, интерпретатор LUA жалуется и сообщает мне, что это нулевой объект. Итак, мой вопрос: правильно ли я поступаю здесь? Можно ли вообще заменить кейграббер так, как я собираюсь?


person JorenHeit    schedule 15.07.2014    source источник
comment
Не могли бы вы рассказать мне больше о катастрофе? Что за сообщение об ошибке? Может быть, какой-нибудь след крушения? И для вашей проблемы: awful.key () - это просто оболочка вокруг key () (прочтите исходный код), которая используется для игнорирования некоторых ключей в привязках клавиш. Так что ваш [1] подход кажется мне странным. Кроме того, когда именно lua жалуется? Когда идет сигнал или когда запускается awesome?   -  person Uli Schlachter    schedule 16.07.2014
comment
@UliSchlachter Crash могло быть неправильным словом. Он замирает, как будто в бесконечном цикле. Без [1] я не смог бы запросить у объекта какие-либо его свойства, поэтому я поместил его туда. Lua пожаловался при попытке подключить сигнал. Оказалось, что во время обновления до 3.5.5, 3.4 не была заменена должным образом, поэтому connect_signal был недоступен. Я исправил это, но теперь многие другие сломались. Придется поработать еще немного. Тем не менее, любопытно, можно ли заменить кейграббер!   -  person JorenHeit    schedule 16.07.2014
comment
@UliSchlachter Update, ошибка при попытке вызвать connect_signal на ключе (без добавления [1]): attempt to call method 'connect_signal' (a nil value) (также в 3.5.5). Это сообщение исчезает при подходе [1], но я еще не видел, чтобы выполнялась подключенная функция.   -  person JorenHeit    schedule 16.07.2014
comment
Хм, я в замешательстве и без идей. Извините   -  person Uli Schlachter    schedule 20.07.2014


Ответы (1)


Чтобы использовать клавишу Alt_L в Awesome, вы должны сослаться на «Mod1» в вашем файле rc.lua, чтобы сделать его более читаемым, я добавил следующую строку в начало моей конфигурации, чтобы можно было использовать Alt_L.

Alt_L = "Mod1"
person switch87    schedule 29.07.2015
comment
Это было давно. В конце концов, я полностью переделал реализацию. Он размещен на github: github.com/jorenheit/awesome_alttab Снимок экрана: raw.githubusercontent.com/jorenheit/awesome_alttab/master/ - person JorenHeit; 30.07.2015
comment
@JorenHeit Я посмотрел на ваш мерзавец, и это оказалось проблемой. Вы считаете, что проблема решена для других людей? Я не нашел его в гугле и должен был выяснить это сам, поэтому я думаю, что люди оценят его здесь. кстати очень красивое расширение. - person switch87; 30.07.2015