From ff131e4ce141deca4507bc73ecbfc173fb4f7f11 Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 11:13:23 +0200 Subject: [PATCH 1/9] Create sharedtags-greedyview --- recipes/sharedtags-greedyview | 115 ++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 recipes/sharedtags-greedyview diff --git a/recipes/sharedtags-greedyview b/recipes/sharedtags-greedyview new file mode 100644 index 0000000..656d85b --- /dev/null +++ b/recipes/sharedtags-greedyview @@ -0,0 +1,115 @@ +# Helper for multiple monitors (based on xrandr) + +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|xrandr.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*. From 39ca7039cdb55f26157aead9111eb3efdd498900 Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 11:13:50 +0200 Subject: [PATCH 2/9] Rename sharedtags-greedyview to sharedtags-greedyview.mdwn --- recipes/{sharedtags-greedyview => sharedtags-greedyview.mdwn} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename recipes/{sharedtags-greedyview => sharedtags-greedyview.mdwn} (100%) diff --git a/recipes/sharedtags-greedyview b/recipes/sharedtags-greedyview.mdwn similarity index 100% rename from recipes/sharedtags-greedyview rename to recipes/sharedtags-greedyview.mdwn From a75f74fe2507d1a47a6c47a1e61876f615af239d Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 11:15:59 +0200 Subject: [PATCH 3/9] Create sharedtags-greedyview.lua --- recipes/sharedtags-greedyview.lua | 195 ++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 recipes/sharedtags-greedyview.lua diff --git a/recipes/sharedtags-greedyview.lua b/recipes/sharedtags-greedyview.lua new file mode 100644 index 0000000..50d5c7f --- /dev/null +++ b/recipes/sharedtags-greedyview.lua @@ -0,0 +1,195 @@ +--- 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/dakling/dakling/awesome-www", + _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 + 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, + 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 + local newsel = screen.selected_tag + newsel.screen = oldscreen + end + local oldsel = oldscreen.selected_tag + tag.screen = screen + + if oldsel == 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 + --else + -- NOTE: A bug in awesome 4.0 is causing all tags to be deselected + -- here. A shame, but I haven't found a nice way to work around it + -- except by fixing the bug (history seems to be in a weird state). + 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(...) return sharedtags.new(select(2, ...)) end }) + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 4a4889110678cd51a314922d62015e2c36327f3a Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 11:20:04 +0200 Subject: [PATCH 4/9] Added sharedtags recipe --- recipes.mdwn | 1 + 1 file changed, 1 insertion(+) diff --git a/recipes.mdwn b/recipes.mdwn index 0366f1c..cafddc3 100644 --- a/recipes.mdwn +++ b/recipes.mdwn @@ -37,6 +37,7 @@ to improve your Awesome setup. * [Collision geometric navigation keybindings](https://github.com/Elv13/collision) * [Tyrannical dynamic tag managment framework](https://github.com/Elv13/tyrannical) * [Repetitive dynamic keybindings and macros](https://github.com/Elv13/repetitive) +* [Alternative tag management for multiple screens](https://github.com/dakling/awesome-sharedtags) ## Others From 2e66eb2f2d4dcf3e30f8482648af2eba1deedbed Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 13:03:58 +0200 Subject: [PATCH 5/9] Update sharedtags-greedyview.mdwn --- recipes/sharedtags-greedyview.mdwn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recipes/sharedtags-greedyview.mdwn b/recipes/sharedtags-greedyview.mdwn index 656d85b..20964c8 100644 --- a/recipes/sharedtags-greedyview.mdwn +++ b/recipes/sharedtags-greedyview.mdwn @@ -1,4 +1,4 @@ -# Helper for multiple monitors (based on xrandr) +# 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: @@ -16,7 +16,7 @@ swapping behaviour described above. 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|xrandr.lua]] content. + awesome's folder) with the [[script|sharedtags-greedyview.lua]] content. 2. Import the script in your `rc.lua` From 08e119cd02239bbcfc74e15cd002b773689764a5 Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 13:07:03 +0200 Subject: [PATCH 6/9] Update recipes.mdwn link to this repository directly --- recipes.mdwn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes.mdwn b/recipes.mdwn index cafddc3..200b14f 100644 --- a/recipes.mdwn +++ b/recipes.mdwn @@ -37,7 +37,7 @@ to improve your Awesome setup. * [Collision geometric navigation keybindings](https://github.com/Elv13/collision) * [Tyrannical dynamic tag managment framework](https://github.com/Elv13/tyrannical) * [Repetitive dynamic keybindings and macros](https://github.com/Elv13/repetitive) -* [Alternative tag management for multiple screens](https://github.com/dakling/awesome-sharedtags) +* [Alternative tag management for multiple screens](../recipes/sharedtags-greedyview) ## Others From 30a0ebd87c515a4ba5c0b17915be092b0cd67380 Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 13:19:17 +0200 Subject: [PATCH 7/9] Update sharedtags-greedyview.lua Implemented suggested changes --- recipes/sharedtags-greedyview.lua | 57 +++++++++++++------------------ 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/recipes/sharedtags-greedyview.lua b/recipes/sharedtags-greedyview.lua index 50d5c7f..3948cec 100644 --- a/recipes/sharedtags-greedyview.lua +++ b/recipes/sharedtags-greedyview.lua @@ -13,7 +13,7 @@ local capi = { 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/dakling/dakling/awesome-www", + _URL = "https://github.com/awesome-www/recipes", _LICENSE = [[ MIT LICENSE @@ -41,33 +41,28 @@ local sharedtags = { -- 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 +capi.screen.connect_signal("removed", function(s) + -- 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 + -- 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.viewmore(seltags, s) end - end) + 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` @@ -92,7 +87,7 @@ function sharedtags.new(def) 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, + screen = t.screen and t.screen or capi.screen.primary, layout = t.layout, sharedtagindex = i }) @@ -123,11 +118,9 @@ function sharedtags.movetag(tag, screen) if oldscreen ~= screen then -- greedyview xmonad-style if tag.selected then - local newsel = screen.selected_tag - newsel.screen = oldscreen + screen.selected_tag.screen = oldscreen end - local oldsel = oldscreen.selected_tag - tag.screen = screen + oldscreen.selected_tag.screen = screen if oldsel == tag then -- The tag has been moved away. In most cases the tag history @@ -139,10 +132,6 @@ function sharedtags.movetag(tag, screen) newtag:view_only() end end - --else - -- NOTE: A bug in awesome 4.0 is causing all tags to be deselected - -- here. A shame, but I haven't found a nice way to work around it - -- except by fixing the bug (history seems to be in a weird state). end -- Also sort the tag in the taglist, by reapplying the index. This is just a nicety. @@ -190,6 +179,6 @@ function sharedtags.viewtoggle(tag, screen) end end -return setmetatable(sharedtags, { __call = function(...) return sharedtags.new(select(2, ...)) 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 From 7642c0c3ec2d7ba3408cc7965093f1f4f778aee4 Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 13:45:50 +0200 Subject: [PATCH 8/9] implemented suggestions --- recipes/sharedtags-greedyview.lua | 48 +++++++++++++++++-------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/recipes/sharedtags-greedyview.lua b/recipes/sharedtags-greedyview.lua index 3948cec..b3c3ff6 100644 --- a/recipes/sharedtags-greedyview.lua +++ b/recipes/sharedtags-greedyview.lua @@ -41,28 +41,33 @@ local sharedtags = { -- Add a signal for each new screen, which just listens for the remove -- event, and moves over all tags when it happens. -capi.screen.connect_signal("removed", function(s) - -- 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 +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.viewmore(seltags, s) + -- 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 - end + 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` @@ -87,7 +92,7 @@ function sharedtags.new(def) for i,t in ipairs(def) do tags[i] = awful.tag.add(t.name or i, { - screen = t.screen and t.screen or capi.screen.primary, + screen = (t.screen and t.screen <= capi.screen.count()) and t.screen or capi.screen.primary, layout = t.layout, sharedtagindex = i }) @@ -120,7 +125,8 @@ function sharedtags.movetag(tag, screen) if tag.selected then screen.selected_tag.screen = oldscreen end - oldscreen.selected_tag.screen = screen + local oldsel = oldscreen.selected_tag + tag.screen = screen if oldsel == tag then -- The tag has been moved away. In most cases the tag history @@ -179,6 +185,6 @@ function sharedtags.viewtoggle(tag, screen) end end -return setmetatable(sharedtags, { __call = function(self, args) return sharedtags.new(args)) 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 From d4a396afbf3e2588eeb86bc587966224fa8a9e65 Mon Sep 17 00:00:00 2001 From: dakling Date: Mon, 30 Apr 2018 16:12:14 +0200 Subject: [PATCH 9/9] improved swapping behaviour --- recipes/sharedtags-greedyview.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recipes/sharedtags-greedyview.lua b/recipes/sharedtags-greedyview.lua index b3c3ff6..0d0c04c 100644 --- a/recipes/sharedtags-greedyview.lua +++ b/recipes/sharedtags-greedyview.lua @@ -124,11 +124,11 @@ function sharedtags.movetag(tag, screen) -- greedyview xmonad-style if tag.selected then screen.selected_tag.screen = oldscreen + oldscreen.selected_tag:view_only() end - local oldsel = oldscreen.selected_tag tag.screen = screen - if oldsel == tag then + 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.