-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added sharedtags-greedyview to recipes #126
base: master
Are you sure you want to change the base?
Changes from all commits
ff131e4
39ca703
a75f74f
4a48891
2e66eb2
08e119c
30a0ebd
7642c0c
d4a396a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
--- Provides functionality to share tags across all screens in awesome WM. | ||
-- @module sharedtags | ||
-- @author Albert Diserholt | ||
-- @copyright 2016 Albert Diserholt | ||
-- @license MIT | ||
|
||
-- Grab environment we need | ||
local awful = require("awful") | ||
local capi = { | ||
screen = screen | ||
} | ||
|
||
local sharedtags = { | ||
_VERSION = "sharedtags v1.0.0 for v4.0", | ||
_DESCRIPTION = "Share tags for awesome window manager v4.0 with greedyview", | ||
_URL = "https://github.com/awesome-www/recipes", | ||
_LICENSE = [[ | ||
MIT LICENSE | ||
|
||
Copyright (c) 2018 Albert Diserholt | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a | ||
copy of this software and associated documentation files (the "Software"), | ||
to deal in the Software without restriction, including without limitation | ||
the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
and/or sell copies of the Software, and to permit persons to whom the | ||
Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
IN THE SOFTWARE. | ||
]] | ||
} | ||
|
||
-- Add a signal for each new screen, which just listens for the remove | ||
-- event, and moves over all tags when it happens. | ||
awful.screen.connect_for_each_screen(function(s) | ||
-- When the screen is removed, all tags need to be moved over to an existing | ||
-- screen. If they are not, accessing the tags will result in an error. It | ||
-- doesn't make sense to fix the error, since clients on the now-hidden tags | ||
-- will automatically be moved to a tag on a visible screen. | ||
s:connect_signal("removed",function() | ||
-- The screen to move the orphaned tags to. | ||
local newscreen = capi.screen.primary | ||
-- The currently selected tags on that screen. | ||
local seltags = newscreen.selected_tags | ||
|
||
-- Move over all tags to an existing screen. | ||
for _,tag in ipairs(s.tags) do | ||
sharedtags.movetag(tag, newscreen) | ||
end | ||
|
||
-- Restore the viewed tags on the new screen. | ||
for i,tag in ipairs(seltags) do | ||
if i == 1 then | ||
tag:view_only() | ||
else | ||
awful.tag.viewtoggle(tag) | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uhm... assuming I understood this correctly, this is the same as |
||
end) | ||
end) | ||
|
||
--- Create new tag objects. | ||
-- The first tag defined for each screen will be automatically selected. | ||
-- @tparam table def A list of tables with the optional keys `name`, `layout` | ||
-- and `screen`. The `name` value is used to name the tag and defaults to the | ||
-- list index. The `layout` value sets the starting layout for the tag and | ||
-- defaults to the first layout. The `screen` value sets the starting screen | ||
-- for the tag and defaults to the first screen. The tags will be sorted in this | ||
-- order in the default taglist. | ||
-- @treturn table A list of all created tags. Tags are assigned numeric values | ||
-- corresponding to the input list, and all tags with non-numerical names are | ||
-- also assigned to a key with the same name. | ||
-- @usage local tags = sharedtags( | ||
-- -- "main" is the first tag starting on screen 2 with the tile layout. | ||
-- { name = "main", layout = awful.layout.suit.tile, screen = 2 }, | ||
-- -- "www" is the second tag on screen 1 with the floating layout. | ||
-- { name = "www" }, | ||
-- -- Third tag is named "3" on screen 1 with the floating layout. | ||
-- {}) | ||
-- -- tags[2] and tags["www"] both refer to the same tag. | ||
function sharedtags.new(def) | ||
local tags = {} | ||
|
||
for i,t in ipairs(def) do | ||
tags[i] = awful.tag.add(t.name or i, { | ||
screen = (t.screen and t.screen <= capi.screen.count()) and t.screen or capi.screen.primary, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's up with |
||
layout = t.layout, | ||
sharedtagindex = i | ||
}) | ||
|
||
-- Create an alias between the index and the name. | ||
if t.name and type(t.name) ~= "number" then | ||
tags[t.name] = tags[i] | ||
end | ||
|
||
-- If no tag is selected for this screen, then select this one. | ||
if not tags[i].screen.selected_tag then | ||
tags[i]:view_only() -- Updates the history as well. | ||
end | ||
end | ||
|
||
return tags | ||
end | ||
|
||
--- Move the specified tag to a new screen, if necessary. | ||
-- @param tag The tag to move. | ||
-- @tparam[opt=awful.screen.focused()] number screen The screen to move the tag to. | ||
-- @treturn bool Whether the tag was moved. | ||
function sharedtags.movetag(tag, screen) | ||
screen = screen or awful.screen.focused() | ||
local oldscreen = tag.screen | ||
|
||
-- If the specified tag is allocated to another screen, we need to move it. | ||
if oldscreen ~= screen then | ||
-- greedyview xmonad-style | ||
if tag.selected then | ||
screen.selected_tag.screen = oldscreen | ||
oldscreen.selected_tag:view_only() | ||
end | ||
tag.screen = screen | ||
|
||
if oldscreen.selected_tag == tag then | ||
-- The tag has been moved away. In most cases the tag history | ||
-- function will find the best match, but if we really want we can | ||
-- try to find a fallback tag as well. | ||
if not oldscreen.selected_tag then | ||
local newtag = awful.tag.find_fallback(oldscreen) | ||
if newtag then | ||
newtag:view_only() | ||
end | ||
end | ||
end | ||
|
||
-- Also sort the tag in the taglist, by reapplying the index. This is just a nicety. | ||
local unpack = unpack or table.unpack | ||
for _,s in ipairs({ screen, oldscreen }) do | ||
local tags = { unpack(s.tags) } -- Copy | ||
table.sort(tags, function(a, b) return a.sharedtagindex < b.sharedtagindex end) | ||
for i,t in ipairs(tags) do | ||
t.index = i | ||
end | ||
end | ||
|
||
return true | ||
end | ||
|
||
return false | ||
end | ||
|
||
--- View the specified tag on the specified screen. | ||
-- @param tag The only tag to view. | ||
-- @tparam[opt=awful.screen.focused()] number screen The screen to view the tag on. | ||
function sharedtags.viewonly(tag, screen) | ||
sharedtags.movetag(tag, screen) | ||
tag:view_only() | ||
end | ||
|
||
--- Toggle the specified tag on the specified screen. | ||
-- The tag will be selected if the screen changes, and toggled if it does not | ||
-- change the screen. | ||
-- @param tag The tag to toggle. | ||
-- @tparam[opt=awful.screen.focused()] number screen The screen to toggle the tag on. | ||
function sharedtags.viewtoggle(tag, screen) | ||
local oldscreen = tag.screen | ||
|
||
if sharedtags.movetag(tag, screen) then | ||
-- Always mark the tag selected if the screen changed. Just feels a lot | ||
-- more natural. | ||
tag.selected = true | ||
-- Update the history on the old and new screens. | ||
oldscreen:emit_signal("tag::history::update") | ||
tag.screen:emit_signal("tag::history::update") | ||
else | ||
-- Only toggle the tag unless the screen moved. | ||
awful.tag.viewtoggle(tag) | ||
end | ||
end | ||
|
||
return setmetatable(sharedtags, { __call = function(self, args) return sharedtags.new(args) end }) | ||
|
||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# Different tag management for multiple monitors | ||
|
||
The [[sharedtags-greedyview.lua|sharedtags-greedyview.lua]] script implements the xmonad default | ||
behaviour in which tags are handled for multiple monitors, namely: | ||
* A list of tags is shared between all screens | ||
* Selecting a tag shows it on the screen that is focused, regardless of the previous screen of the tag (greedyview) | ||
* If the selected tag was already visible on the other screen, swap tags between screens | ||
|
||
# Credit | ||
|
||
I forked the script from https://github.com/Elv13/awesome-sharedtags and only added a few lines to implement the | ||
swapping behaviour described above. | ||
|
||
# Setup | ||
|
||
The process of setting up this script is as follows: | ||
|
||
1. Create a file called `sharedtags-greedyview.lua` in your file system (preferably in | ||
awesome's folder) with the [[script|sharedtags-greedyview.lua]] content. | ||
|
||
2. Import the script in your `rc.lua` | ||
|
||
```lua | ||
local sharedtags = require("sharedtags-greedyview") | ||
``` | ||
|
||
3. Create the tags using the `sharedtags()` method, instead of the original | ||
ones created with `awful.tag()`. They should be created at the file level, | ||
i.e. outside of any function. | ||
|
||
```lua | ||
local tags = sharedtags({ | ||
{ name = "main", layout = awful.layout.layouts[2] }, | ||
{ name = "www", layout = awful.layout.layouts[10] }, | ||
{ name = "game", layout = awful.layout.layouts[1] }, | ||
{ name = "misc", layout = awful.layout.layouts[2] }, | ||
{ name = "chat", screen = 2, layout = awful.layout.layouts[2] }, | ||
{ layout = awful.layout.layouts[2] }, | ||
{ screen = 2, layout = awful.layout.layouts[2] } | ||
}) | ||
``` | ||
4. Remove or uncomment the code which creates the tags when a screen is | ||
connected, in the `connect_for_each_screen` callback. | ||
|
||
```lua | ||
awful.screen.connect_for_each_screen(function(s) | ||
-- Each screen has its own tag table. | ||
--awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1]) | ||
|
||
-- Here is a good place to add tags to a newly connected screen, if desired: | ||
--sharedtags.viewonly(tags[4], s) | ||
end) | ||
``` | ||
5. The code for handling tags and clients needs to be changed to use the | ||
library and pick the correct tag. | ||
|
||
```lua | ||
for i = 1, 9 do | ||
globalkeys = gears.table.join(globalkeys, | ||
-- View tag only. | ||
awful.key({ modkey }, "#" .. i + 9, | ||
function () | ||
local screen = awful.screen.focused() | ||
local tag = tags[i] | ||
if tag then | ||
sharedtags.viewonly(tag, screen) | ||
end | ||
end, | ||
{description = "view tag #"..i, group = "tag"}), | ||
-- Toggle tag display. | ||
awful.key({ modkey, "Control" }, "#" .. i + 9, | ||
function () | ||
local screen = awful.screen.focused() | ||
local tag = tags[i] | ||
if tag then | ||
sharedtags.viewtoggle(tag, screen) | ||
end | ||
end, | ||
{description = "toggle tag #" .. i, group = "tag"}), | ||
-- Move client to tag. | ||
awful.key({ modkey, "Shift" }, "#" .. i + 9, | ||
function () | ||
if client.focus then | ||
local tag = tags[i] | ||
if tag then | ||
client.focus:move_to_tag(tag) | ||
end | ||
end | ||
end, | ||
{description = "move focused client to tag #"..i, group = "tag"}), | ||
-- Toggle tag on focused client. | ||
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, | ||
function () | ||
if client.focus then | ||
local tag = tags[i] | ||
if tag then | ||
client.focus:toggle_tag(tag) | ||
end | ||
end | ||
end, | ||
{description = "toggle focused client on tag #" .. i, group = "tag"}) | ||
) | ||
end | ||
``` | ||
6. Lastly, any rules referencing the screen and tag should use the newly | ||
created `tags` array instead. | ||
|
||
```lua | ||
awful.rules.rules = { | ||
-- Set Firefox to always map on tag number 2. | ||
{ rule = { class = "Firefox" }, | ||
properties = { tag = tags[2] } }, -- or tags["www"] to map it to the name instead | ||
} | ||
``` | ||
7. Restart or reload *awesome*. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two signal connections can be replaced with just
capi.screen.connect_signal("removed", function(s)
.