first commit
This commit is contained in:
commit
e8294b0847
349
README.md
Normal file
349
README.md
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
|
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
|
||||||
|
|
||||||
|
- [awesome-cyclefocus](#awesome-cyclefocus)
|
||||||
|
- [Screenshot](#screenshot)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Keybindings](#keybindings)
|
||||||
|
- [Example 1: cycle through all windows](#example-1-cycle-through-all-windows)
|
||||||
|
- [Example 2: cycle through windows on the same screen and tag](#example-2-cycle-through-windows-on-the-same-screen-and-tag)
|
||||||
|
- [`cycle_filters`](#cycle_filters)
|
||||||
|
- [Predefined filters](#predefined-filters)
|
||||||
|
- [Example 3: cycle through clients with the same class](#example-3-cycle-through-clients-with-the-same-class)
|
||||||
|
- [Reference](#reference)
|
||||||
|
- [Configuration](#configuration)
|
||||||
|
- [<a name="settings"></a>Settings](#a-namesettingsasettings)
|
||||||
|
- [Status](#status)
|
||||||
|
- [Bugs, Feedback and Support](#bugs-feedback-and-support)
|
||||||
|
- [Donate](#donate)
|
||||||
|
|
||||||
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
|
||||||
|
# awesome-cyclefocus
|
||||||
|
|
||||||
|
awesome-cyclefocus is a module/plugin for the [awesome window
|
||||||
|
manager][], which provides methods to cycle through
|
||||||
|
the most recently used clients (typically known as Alt-Tab).
|
||||||
|
|
||||||
|
It allows to easily filter the list of windows to be cycled through, e.g. by
|
||||||
|
screen, tags, window class, name/title etc.
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Please note that the graphical aspect needs to be developed, but since people
|
||||||
|
like screenshots…
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
*Requirements:* awesome-cyclefocus requires Awesome 4+.
|
||||||
|
|
||||||
|
Create a subdirectory `cyclefocus` in your awesome config directory, e.g.
|
||||||
|
|
||||||
|
cd ~/.config/awesome
|
||||||
|
git clone https://github.com/blueyed/awesome-cyclefocus cyclefocus
|
||||||
|
|
||||||
|
Then include it from your config file (`~/.config/awesome/rc.lua`), somewhere
|
||||||
|
at the beginning:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local cyclefocus = require('cyclefocus')
|
||||||
|
```
|
||||||
|
|
||||||
|
## Keybindings
|
||||||
|
|
||||||
|
Then you can define the keybindings.
|
||||||
|
|
||||||
|
While you can use it with the `globalkeys` configuation, you should use
|
||||||
|
the `clientkeys` table for any bindings which use `cycle_filters`.
|
||||||
|
|
||||||
|
The default for `modkey+Tab` in awesome (3.5.2) is:
|
||||||
|
```lua
|
||||||
|
awful.key({ modkey, }, "Tab",
|
||||||
|
function ()
|
||||||
|
awful.client.focus.history.previous()
|
||||||
|
if client.focus then
|
||||||
|
client.focus:raise()
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
```
|
||||||
|
You should disable it (e.g. by commenting it out), and add your method below.
|
||||||
|
|
||||||
|
Here are three methods to setup the key mappings:
|
||||||
|
|
||||||
|
### Example 1: cycle through all windows
|
||||||
|
|
||||||
|
Setup `modkey+Tab` to cycle through all windows (assuming `modkey` is
|
||||||
|
`Mod4`/`Super_L`, which is the default):
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- modkey+Tab: cycle through all clients.
|
||||||
|
awful.key({ modkey }, "Tab", function(c)
|
||||||
|
cyclefocus.cycle({modifier="Super_L"})
|
||||||
|
end),
|
||||||
|
-- modkey+Shift+Tab: backwards
|
||||||
|
awful.key({ modkey, "Shift" }, "Tab", function(c)
|
||||||
|
cyclefocus.cycle({modifier="Super_L"})
|
||||||
|
end),
|
||||||
|
```
|
||||||
|
|
||||||
|
You can pass a table of optional arguments.
|
||||||
|
We need to pass the modifier (as seen by awesome's `keygrabber`) here.
|
||||||
|
Internally the direction gets set according to if the `Shift` modifier key
|
||||||
|
is present, so that the second definition is only necessary to trigger it in
|
||||||
|
the opposite direction from the beginning.
|
||||||
|
|
||||||
|
See the `init.lua` file (or the [settings section below](#settings)) for a full
|
||||||
|
reference.
|
||||||
|
|
||||||
|
### Example 2: cycle through windows on the same screen and tag
|
||||||
|
|
||||||
|
You can use `cyclefocus.key` (a wrapper around `awful.key`) like this:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Alt-Tab: cycle through clients on the same screen.
|
||||||
|
-- This must be a clientkeys mapping to have source_c available in the callback.
|
||||||
|
cyclefocus.key({ "Mod1", }, "Tab", {
|
||||||
|
-- cycle_filters as a function callback:
|
||||||
|
-- cycle_filters = { function (c, source_c) return c.screen == source_c.screen end },
|
||||||
|
|
||||||
|
-- cycle_filters from the default filters:
|
||||||
|
cycle_filters = { cyclefocus.filters.same_screen, cyclefocus.filters.common_tag },
|
||||||
|
keys = {'Tab', 'ISO_Left_Tab'} -- default, could be left out
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
|
||||||
|
The first two arguments are the same as with `awful.key`: a list of modifiers
|
||||||
|
and the key. Then the table with optional arguments to `cyclefocus.cycle()`
|
||||||
|
follows.
|
||||||
|
(here the `modifier` argument is not required, because it gets used from
|
||||||
|
the first argument).
|
||||||
|
|
||||||
|
NOTE: this needs to go into `clientkeys`.
|
||||||
|
|
||||||
|
#### `cycle_filters`
|
||||||
|
|
||||||
|
In this case the `cycle_filters` argument is used, which is a list of filters
|
||||||
|
to apply while cycling through the focus history: it gets passed a `client`
|
||||||
|
object, and optionally another `client` object for the source (where the
|
||||||
|
cycling started).
|
||||||
|
For the source client to be available, it needs to be an entry in the
|
||||||
|
`clientkeys` table.
|
||||||
|
|
||||||
|
You can pass functions here, or use one of the predefined filters:
|
||||||
|
|
||||||
|
#### Predefined filters
|
||||||
|
|
||||||
|
The following filters are available by default:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- A set of default filters, which can be used for cyclefocus.cycle_filters.
|
||||||
|
cyclefocus.filters = {
|
||||||
|
-- Filter clients on the same screen.
|
||||||
|
same_screen = function (c, source_c) return c.screen == source_c.screen end,
|
||||||
|
|
||||||
|
same_class = function (c, source_c)
|
||||||
|
return c.class == source_c.class
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Only marked clients (via awful.client.mark and .unmark).
|
||||||
|
marked = function (c, source_c)
|
||||||
|
return awful.client.ismarked(c)
|
||||||
|
end,
|
||||||
|
|
||||||
|
common_tag = function (c, source_c)
|
||||||
|
for _, t in pairs(c:tags()) do
|
||||||
|
for _, t2 in pairs(source_c:tags()) do
|
||||||
|
if t == t2 then
|
||||||
|
cyclefocus.debug("Filter: client shares tag '" .. t.name .. " with " .. c.name)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: cycle through clients with the same class
|
||||||
|
|
||||||
|
The following will cycle through windows, which share the same window class
|
||||||
|
(e.g. only Firefox windows, when starting from a Firefox window):
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- Alt-^: cycle through clients with the same class name.
|
||||||
|
cyclefocus.key({ "Mod1", }, "#49", 1, {
|
||||||
|
cycle_filter = function (c, source_c) return c.class == source_c.class end,
|
||||||
|
keys = { "°", "^" }, -- the keys to be handled, wouldn't be required if the keycode was available in keygrabber.
|
||||||
|
}),
|
||||||
|
cyclefocus.key({ "Mod1", "Shift", }, "#49", -1, { -- keycode #49 => ^/° on german keyboard, upper left below Escape and next to 1.
|
||||||
|
cycle_filter = function (c, source_c) return c.class == source_c.class end,
|
||||||
|
keys = { "°", "^" }, -- the keys to be handled, wouldn't be required if the keycode was available in keygrabber.
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
|
||||||
|
The key argument uses the keycode notation (`#49`) and refers (probably) to the key
|
||||||
|
below Escape, above Tab and next to the first digit (1).
|
||||||
|
It should be the same shortcut, as what Ubuntu's Unity uses to cycle through
|
||||||
|
the windows of a single application.
|
||||||
|
|
||||||
|
NOTE: You need to pass the keys this refers to via the `keys` argument, so that
|
||||||
|
the keygrabber considers those only.
|
||||||
|
In the example above, `^` and `°` refers to the key on the German keyboard
|
||||||
|
layout (un-shifted and shifted, i.e. with Shift pressed and released).
|
||||||
|
|
||||||
|
NOTE: this needs to go into `clientkeys`.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
awesome-cyclefocus can be configured by passing optional arguments to the
|
||||||
|
`cyclefocus.cycle` or `cyclefocus.key` functions, or by setting defaults, after
|
||||||
|
loading `cyclefocus`:
|
||||||
|
|
||||||
|
#### <a name="settings"></a>Settings
|
||||||
|
|
||||||
|
The default settings are:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
cyclefocus = {
|
||||||
|
-- Should clients get shown during cycling?
|
||||||
|
-- This should be a function (or `false` to disable showing clients), which
|
||||||
|
-- receives a client object, and can make use of cyclefocus.show_client
|
||||||
|
-- (the default implementation).
|
||||||
|
show_clients = true,
|
||||||
|
-- Should clients get focused during cycling?
|
||||||
|
-- This is required for the tasklist to highlight the selected entry.
|
||||||
|
focus_clients = true,
|
||||||
|
|
||||||
|
-- How many entries should get displayed before and after the current one?
|
||||||
|
display_next_count = 3,
|
||||||
|
display_prev_count = 3,
|
||||||
|
|
||||||
|
-- Default preset to for entries.
|
||||||
|
-- `preset_for_offset` (below) gets added to it.
|
||||||
|
default_preset = {},
|
||||||
|
|
||||||
|
--- Templates for entries in the list.
|
||||||
|
-- The following arguments get passed to a callback:
|
||||||
|
-- - client: the current client object.
|
||||||
|
-- - idx: index number of current entry in clients list.
|
||||||
|
-- - displayed_list: the list of entries in the list, possibly filtered.
|
||||||
|
preset_for_offset = {
|
||||||
|
-- Default callback, which will gets applied for all offsets (first).
|
||||||
|
default = function (preset, args)
|
||||||
|
-- Default font and icon size (gets overwritten for current/0 index).
|
||||||
|
preset.font = 'sans 8'
|
||||||
|
preset.icon_size = 36
|
||||||
|
preset.text = escape_markup(cyclefocus.get_client_title(args.client, false))
|
||||||
|
|
||||||
|
preset.icon = cyclefocus.icon_loader(args.client.icon)
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- Preset for current entry.
|
||||||
|
["0"] = function (preset, args)
|
||||||
|
preset.font = 'sans 12'
|
||||||
|
preset.icon_size = 48
|
||||||
|
preset.text = escape_markup(cyclefocus.get_client_title(args.client, true))
|
||||||
|
-- Add screen number if there is more than one.
|
||||||
|
if screen.count() > 1 then
|
||||||
|
preset.text = preset.text .. " [screen " .. tostring(args.client.screen.index) .. "]"
|
||||||
|
end
|
||||||
|
preset.text = preset.text .. " [#" .. args.idx .. "] "
|
||||||
|
preset.text = '<b>' .. preset.text .. '</b>'
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- You can refer to entries by their offset.
|
||||||
|
-- ["-1"] = function (preset, args)
|
||||||
|
-- -- preset.icon_size = 32
|
||||||
|
-- end,
|
||||||
|
-- ["1"] = function (preset, args)
|
||||||
|
-- -- preset.icon_size = 32
|
||||||
|
-- end
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Default builtin filters.
|
||||||
|
-- (meant to get applied always, but you could override them)
|
||||||
|
cycle_filters = {
|
||||||
|
function(c, source_c) return not c.minimized end, --luacheck: no unused args
|
||||||
|
},
|
||||||
|
|
||||||
|
-- EXPERIMENTAL: only add clients to the history that have been focused by
|
||||||
|
-- cyclefocus.
|
||||||
|
-- This allows to switch clients using other methods, but those are then
|
||||||
|
-- not added to cyclefocus' internal history.
|
||||||
|
-- The get_next_client function will then first consider the most recent
|
||||||
|
-- entry in the history stack, if it's not focused currently.
|
||||||
|
--
|
||||||
|
-- You can use cyclefocus.history.add to manually add an entry, or
|
||||||
|
-- cyclefocus.history.append if you want to add it to the end of the stack.
|
||||||
|
-- This might be useful in a request::activate signal handler.
|
||||||
|
-- only_add_internal_focus_changes_to_history = true,
|
||||||
|
|
||||||
|
-- The filter to ignore clients altogether (get not added to the history stack).
|
||||||
|
-- This is different from the cycle_filters.
|
||||||
|
-- The function should return true / the client if it's ok, nil otherwise.
|
||||||
|
filter_focus_history = awful.client.focus.filter,
|
||||||
|
|
||||||
|
-- Display notifications while cycling?
|
||||||
|
-- WARNING: without raise_clients this will not make sense probably!
|
||||||
|
display_notifications = true,
|
||||||
|
|
||||||
|
-- Debugging: messages get printed, and should show up in ~/.xsession-errors etc.
|
||||||
|
-- 1: enable, 2: verbose, 3: very verbose, 4: much verbose.
|
||||||
|
debug_level = 0,
|
||||||
|
-- Use naughty notifications for debugging (additional to printing)?
|
||||||
|
debug_use_naughty_notify = 1,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can change them like this:
|
||||||
|
```lua
|
||||||
|
cyclefocus = require("cyclefocus")
|
||||||
|
cyclefocus.debug_level = 2
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use custom settings when calling `cyclefocus.cycle` or
|
||||||
|
`cyclefocus.key` via `args`, e.g. to not display notifications when switching
|
||||||
|
between clients on the same tag:
|
||||||
|
```lua
|
||||||
|
cyclefocus.key({ modkey, }, "Tab", 1, {
|
||||||
|
cycle_filters = { cyclefocus.filters.common_tag },
|
||||||
|
display_notifications = false,
|
||||||
|
modifier='Super_L', keys={'Tab', 'ISO_Left_Tab'}
|
||||||
|
}),
|
||||||
|
cyclefocus.key({ modkey, "Shift", }, "Tab", 1, {
|
||||||
|
cycle_filters = { cyclefocus.filters.common_tag },
|
||||||
|
display_notifications = false,
|
||||||
|
modifier='Super_L', keys={'Tab', 'ISO_Left_Tab'}
|
||||||
|
}),
|
||||||
|
```
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Stable: it works well for me and others.
|
||||||
|
Internals, default settings and behavior might still change.
|
||||||
|
|
||||||
|
I came up with this while dipping my toes in the waters of awesome. If you have
|
||||||
|
problems, please enable `cyclefocus.debug_level` (goes up to 3) and report your
|
||||||
|
findings on the [Github issue tracker][].
|
||||||
|
|
||||||
|
# Bugs, Feedback and Support
|
||||||
|
|
||||||
|
You can report bugs and wishes at the [Github issue tracker][].
|
||||||
|
|
||||||
|
Pull requests would be awesome! :)
|
||||||
|
|
||||||
|
## Donate
|
||||||
|
|
||||||
|
[](https://flattr.com/submit/auto?user_id=blueyed&url=https://github.com/blueyed/awesome-cyclefocus&title=awesome-cyclefocus&language=en&tags=github&category=software)
|
||||||
|
|
||||||
|
Bitcoin: 16EVhEpXxfNiT93qT2uxo4DsZSHzNdysSp
|
||||||
|
|
||||||
|
[awesome window manager]: http://awesome.naquadah.org/
|
||||||
|
[Github issue tracker]: https://github.com/blueyed/awesome-cyclefocus/issues
|
||||||
|
# awesome-cyclefocus-fork
|
||||||
|
# awesome-cyclefocus-fork
|
Loading…
x
Reference in New Issue
Block a user