Code Monkey home page Code Monkey logo

tyrannical's Introduction

Tyrannical—A simple tag managment engine for Awesome

News

January 2019

Tyrannical 2.0.0 has been released. It is the first and last official release for Awesome 4.0 to 4.2. The new no_tag_deselect option has been added ( thanks to @cherti).

From now on, only AwesomeWM 4.3+ is supported. Parts of Tyrannical were merged into AwesomeWM 4.3 and it will make everything more reliable.

April 2016

Tyrannical 1.0.0 has been released. This is the first and last version for Awesome 3.5. Tyrannical is still in active developement and a brand new implementation will be released shortly after Awesome 4.0 is released.

Tyrannical goal is and has always been to avoid re-inventing the wheel and use existing Awesome APIs to manage tags. This will now get much easier with Awesome 4.0 and a new "request" API designed with Tyrannical like workflows in mind. This will avoid turning the code into a unreadable ball of spagetti as the current implementation became.

December 2016

The master branch is for Awesome 4.4+. If you use Awesome 3.5, use the 1.0.0 version. If you use Awesome 4.0-2.4, use the 2.0.0 version.

Description

Tyrannical is a tag management system for Awesome 3.5+. It is inspired and intend to replace the Shifty module popular in older versions of Awesome.

Compared to Shifty, Tyrannical doesn't try to replace awful.tag and awful.rules, but rather extend them to support the following features:

  • Declarative tags declaration description
  • Rules based around the tags rather than the clients
  • Rules based around the client properties rather than the clients
  • A dynamic tag workflow where tags are created and removed on demand
  • A stateful tag model
  • More powerful focus stealing rules

Tyrannical was created because:

  • Shifty code is too complex and outdated to be maintained
  • awful support dynamic tagging, but it's awkward to use
  • It implements a workflow that better fit my taste than the default one

Tyrannical 1.0 versus 2.0-alpha:

While I am among the first AwesomeWM user, I only became a major contributor during the 4.0 development cycle. The new version of Awesome has new APIs designed to improve alternate workflows such as the one proposed by Tyrannical.

The new version aims to rewrite Tyrannical to use these APIs instead of the hacks that allowed the original version to work. The original code also became unmaintainable due to horrible coding practices and repeated hacks to fine tune its behavior.

Finally, Awesome 4.0 introduces support for adding and removing screen at runtime. Therefor, being able to expand and contract the tag set dynamically is finally possible. Being able to support the use case where a laptop is optionally plugged to an external monitor will be implemented once feature parity has been achieved.

Future:

My first attempt at implementing dynamic layouts failed back in 2012, but for a year I have been using a new implementation. This isn't expected to land in Awesome anytime soon. But once it does, Tyrannical will gain the ability to describe whole dynamic layouts instead of "just" its tag.

Tag model

Tyrannical turn awful.rule upside down. Instead of having to define rules for specific classes or matches, you define an array of tags, each with their own set of properties and rules. When a new client will arrive, it will be matched with a set of tags without any client specific configuration.

All tags can have one "current" state:

  • inclusive: The default state. All new clients will be allowed
  • exclusive: Clients have be part of the allowed classes to be added
  • locked: No new clients will be allowed in the tag
  • fallback: If a client cannot be added to the current tag, then it will go there

These rules are bypassed by intrusive clients. In that case, the client will be allowed no matter what. If there is no fallback tag and the client cannot be added to an existing tag, then a new one will be created with the client class as name. If the tag is set to volatile, then it will be destroyed when the last client is closed. If set to init, it will be present by default even if there is nothing in it.

Client properties model

Tyrannical offer a bunch of dynamic table for each properties (see below). When a class is present in one of those table, clients will be assigned the properties from the table name. For example, if you add Firefox to tyrannical.properties.floating, then it will float by default. Specific values can also to other value by using the class name as table key:

tyrannical.properties.maximized = {
    amarok = false,
}

Focus model

Tyrannical focus model is very fine tuned. It is possible to add rules on how the focus will be attributes to clients and tags.

block_children_focus_stealing: This is a fancy X11 name for something very common: modal dialogs and popups. If this is set to true, then a dialog wont be able to steal the focus from whatever your doing. This is useful for some misbehaving apps such as Firefox that can decide to show an update popup at the worst possible moment.

group_children: While not directly related to focus, when using with no_focus_stealing_out, it allow new "children" clients to silently be added to their "parent" tag. A good taglist widgets such as Radical can take care of notifying the user without disturbing your workflow.

no_focus_stealing_in: When a new client is added to a tag with no_focus_stealing_in set to true, then the tag wont be selected and the current one will be kept.

no_focus_stealing_out: Similar to no_focus_stealing_in. If a tag enable this, then the tag will stay selected no matter what event happen. This is useful for video games and video players.

no_tag_deselect: When a new client is added somewhere, that tag gets selected in addition to the current selection of tags instead of being selected solely.

no_autofocus: When a class has this flag, then new clients wont be focused when they are launched. This is useful for download managers or background terminals tasks.

Installation

This is how to install Tyrannical for Awesome 4.X:

mkdir -p ~/.config/awesome
cd ~/.config/awesome
git clone https://github.com/Elv13/tyrannical.git

Awesome 3.5 users should fetch the version 1.0.0.

Then either use the sample rc.lua or upgrade your existing one.

Configuration

If you previously used Shifty, you will feel comfortable using Tyrannical. The only difference is that in Tyrannical class matching is integrated into the tag configuration section. More advanced rules can be created using awful.rules. Again, Tyrannical was not created to duplicate awful, but to make dynamic (and static, as a side effect) tagging configuration easier. This module doesn't require any major initialisation. Compared to shifty, it is much more transparent.

The first modification is to include the module at the top of your rc.lua (after awful.rules = require("awful.rules")):

local tyrannical = require("tyrannical")
--require("tyrannical.shortcut") --optional

Then this line has to be removed:

awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])

And this added outside of the awful.screen.connect_for_each_screen section:

tyrannical.tags = {
    {
        name        = "Term",                 -- Call the tag "Term"
        init        = true,                   -- Load the tag on startup
        exclusive   = true,                   -- Refuse any other type of clients (by classes)
        screen      = {1,2},                  -- Create this tag on screen 1 and screen 2
        layout      = awful.layout.suit.tile, -- Use the tile layout
        instance    = {"dev", "ops"},         -- Accept the following instances. This takes precedence over 'class'
        class       = { --Accept the following classes, refuse everything else (because of "exclusive=true")
            "xterm" , "urxvt" , "aterm","URxvt","XTerm","konsole","terminator","gnome-terminal"
        }
    } ,
    {
        name        = "Internet",
        init        = true,
        exclusive   = true,
      --icon        = "~net.png",                 -- Use this icon for the tag (uncomment with a real path)
        screen      = screen.count()>1 and 2 or 1,-- Setup on screen 2 if there is more than 1 screen, else on screen 1
        layout      = awful.layout.suit.max,      -- Use the max layout
        class = {
            "Opera"         , "Firefox"        , "Rekonq"    , "Dillo"        , "Arora",
            "Chromium"      , "nightly"        , "minefield"     }
    } ,
    {
        name        = "Files",
        init        = true,
        exclusive   = true,
        screen      = 1,
        layout      = awful.layout.suit.tile,
        exec_once   = {"dolphin"}, --When the tag is accessed for the first time, execute this command
        class  = {
            "Thunar", "Konqueror", "Dolphin", "ark", "Nautilus","emelfm"
        }
    } ,
    {
        name        = "Develop",
        init        = true,
        exclusive   = true,
        screen      = 1,
        layout      = awful.layout.suit.max                          ,
        class ={
            "Kate", "KDevelop", "Codeblocks", "Code::Blocks" , "DDD", "kate4"}
    } ,
    {
        name        = "Doc",
        init        = false, -- This tag wont be created at startup, but will be when one of the
                             -- client in the "class" section will start. It will be created on
                             -- the client startup screen
        exclusive   = true,
        layout      = awful.layout.suit.max,
        class       = {
            "Assistant"     , "Okular"         , "Evince"    , "EPDFviewer"   , "xpdf",
            "Xpdf"          ,                                        }
    } ,
}

-- Ignore the tag "exclusive" property for the following clients (matched by classes)
tyrannical.properties.intrusive = {
    "ksnapshot"     , "pinentry"       , "gtksu"     , "kcalc"        , "xcalc"               ,
    "feh"           , "Gradient editor", "About KDE" , "Paste Special", "Background color"    ,
    "kcolorchooser" , "plasmoidviewer" , "Xephyr"    , "kruler"       , "plasmaengineexplorer",
}

-- Ignore the tiled layout for the matching clients
tyrannical.properties.floating = {
    "MPlayer"      , "pinentry"        , "ksnapshot"  , "pinentry"     , "gtksu"          ,
    "xine"         , "feh"             , "kmix"       , "kcalc"        , "xcalc"          ,
    "yakuake"      , "Select Color$"   , "kruler"     , "kcolorchooser", "Paste Special"  ,
    "New Form"     , "Insert Picture"  , "kcharselect", "mythfrontend" , "plasmoidviewer"
}

-- Make the matching clients (by classes) on top of the default layout
tyrannical.properties.ontop = {
    "Xephyr"       , "ksnapshot"       , "kruler"
}

-- Force the matching clients (by classes) to be centered on the screen on init
tyrannical.properties.placement = {
    kcalc = awful.placement.centered
}

tyrannical.settings.block_children_focus_stealing = true --Block popups ()
tyrannical.settings.group_children = true --Force popups/dialogs to have the same tags as the parent client

Then edit this section to fit your needs.

The available tag properties are:
Property Description Type
class Match these classes to this tag array of string
instance Match these instances to this tag. ★ array of string
exclusive Allow only client from the "class" attributes boolean
exec_once Execute when the tag is first selected string (command)
force_screen Force a screen boolean
hide Hide this tag from view boolean
icon Tag icon path
init Create when awesome launch boolean
layout The tag layout layout
master_width_factor Tiled layout master/slave ratio float(0-1)
column_count Number of columns number
master_count Number of master clients number
no_focus_stealing_in Do not select this tag when a new client is added boolean
no_focus_stealing_out Do not unselect when a new client is added elsewhere boolean
no_tag_deselect Do not unselect other tags spawning/selecting this boolean
screen Tag screen(s) number or array
selected Select when created boolean
volatile Destroy when the last client is closed boolean
fallback Use this tag for unmatched clients boolean
locked Do not add any more clients to this tag boolean
max_clients Maximum number of clients before creating a new tag number or func
onetimer Once deleted, this tag cannot be created again boolean

★Takes precedence over class

See: http://new.awesomewm.org/apidoc/classes/tag.html

The available client properties are:

Note that every property can also be a function. In that case it has a client as the first parameter and the property array as the second. It must return a value with a compatible type. Those properties are directly converted into awful.rules.

Property Description Type
above Display above other clients boolean
below Display below other clients boolean
border_color Change client default border color* string
border_width Change the client border width number
placement Center the client on the screen at launch awful.placement
floating Make the client floating or insert into layout boolean
focusable Allow focus boolean
fullscreen Cover the whole screen boolean
hidden Hide this client (minimize) boolean
intrusive Ignore tag "exclusive" property boolean
maximized_horizontal Cover all horizontal space boolean
maximized_vertical Cover all vertical space boolean
ontop Display on top of the normal layout layer boolean
skip_taskbar Do not add to tasklist boolean
sticky Display in all tags boolean
master Open a client as master (bigger) boolean
slave Open a client as slave (smaller) boolean
no_autofocus Do not focus a new instance boolean
tag Asign to a pre-existing tag object tag/array/string
tags Asign to a pre-existing tag object array
new_tag Do not focus a new instance boolean or array
callback A function returning an array or properties function

*Need default rc.lua modifications in the "client.connect_signal('focus')" section

See:

The available global settings are:
Property Description Type
block_children_focus_stealing Prevent popups from stealing focus boolean
default_layout The default layout for tags layout
group_children Add dialogs to the same tags as their parent client boolean
master_width_factor The default master/slave ratio float (0-1)
force_odd_as_intrusive Make all non-normal (dock, splash) intrusive boolean
no_focus_stealing_out Do not unselect tags when a new client is added boolean
favor_focused Prefer the focused screen to the screen property boolean

It's worth noting that some settings like master_width_factor and default_layout should be set before the tag arrow. Otherwise they wont take effect at startup.

favor_focused Is enabled by default for tags created after startup for convinience. Use force_screen or tyrannical.settings.favor_focused = false to do otherwise.


FAQ

Is Tyrannical under active development

Yes.

Note that the Tyrannical feature set is complete and the scope isn't likely to be expanded. The new features, if any, are intended to refining the current algorithm. Parts by part, Tyrannical features are upstreamed into Awesome itself and it is where the main development is happening.

Is it possible to add, remove and move tags?

Yes, this feature is now part of awful. It does not require an external module anymore. Awful's dynamic tag implementation is compatible with Tyrannical. See the API and this user contribution

How do I get a client class?

From a terminal, execute xprop, then click on an instance of that client. There will be a "CLASS" line with one or more class. Always pick the second one, Tyrannical is not case sensitive.

Is it possible to have relative indexes (position) for tags?

Tyrannical shares awful's tag list. It does not keep its own indexes since this would make it harder to implement this feature in the core. Given that, this feature is outside the project scope. That being said, nothing prevents you from adding a "position" property to the tag. Once this is done, edit the default rc.lua keybindings to find the position by looping the tags. In case the tag is not yet created, you can access it with tyrannical.tags_by_name["your tag name"] array. This array is automatically generated. You can then add it using awful.tag.add(tyrannical.tags_by_name["your tag name"].name,tyrannical.tags_by_name["your tag name"]). Tyrannical's purpose is not to duplicate or change awful.tag behavior, it is simply a configuration wrapper.

Is it possible to change the layout when adding a new client?

Yes and no. There is a workaround using a max_clients callback. This function has to return a number of clients for a given tag, but can also be used to alter them. The function take a client as first parameter and a possible tag as the second. Returning 0 will always force a new tag to be created. Returning nil will allow the client into that tag. This function switch between tile and magnifier:

local function aero_or_magnifier(c,tag)
    local count = #match:clients() + 1 --The client is not there yet
    if count == 2 then
        tag.layout = awful.layout.suit.tile
        tag.master_width_factor = 0.5
    else
        tag.layout = awful.layout.suit.magnifier
    end
    return 5 -- Use a maximum of 5 clients
end

Is it possible to directly launch clients in the current tag or a new one?

This feature is mostly available for Awesome 3.5.3+, 3.5.6+ is recommanded. Tyrannical will use the "startup notification" field in clients that support it to track a spawn request. Some applications, such as GVim and XTerm, doesn't support this. URxvt, Konsole and Gnome terminal does.

Here are some example:

-- Spawn in a new tag
awful.spawn("urxvt",{new_tag=true})

-- Or for more advanced use case, you can use a full tag definition too
awful.spawn("urxvt",{ new_tag= {
   name = "MyNewTag",
   exclusive = true,
})

-- Spawn in the current tag, floating and on top
awful.spawn(terminal,{intrusive=true, floating=true, ontop=true})

-- Spawn in an existing tag (assume `my_tag` exist)
-- Note that `tag` can also be an array of tags or a function returning
-- an array of tags
awful.spawn(terminal,{tag=my_tag})

For Awesome 3.5.6+, it is possible to replace the default mod4+r keybinding with a more powerful one:

awful.key({ modkey }, "r",
    function ()
        awful.prompt.run({ prompt = "Run: ", hooks = {
            {{         },"Return",function(command)
                local result = awful.spawn(command)
                mypromptbox[mouse.screen].widget:set_text(type(result) == "string" and result or "")
                return true
            end},
            {{"Mod1"   },"Return",function(command)
                local result = awful.spawn(command,{intrusive=true})
                mypromptbox[mouse.screen].widget:set_text(type(result) == "string" and result or "")
                return true
            end},
            {{"Shift"  },"Return",function(command)
                local result = awful.spawn(command,{intrusive=true,ontop=true,floating=true})
                mypromptbox[mouse.screen].widget:set_text(type(result) == "string" and result or "")
                return true
            end}
        }},
        mypromptbox[mouse.screen].widget,nil,
        awful.completion.shell,
        awful.util.getdir("cache") .. "/history")
    end),

When using this, instead of pressing Return to spawn the application, you can use Alt+Return to launch it as an intrusive client. You can add more sections to support more use case (such as Shift+Return to launch as floating as shown above)

Can I alter the client properties based on runtime criterias?

Yes, everytime Tyrannical consider a client, it will call the callback function. This function can return an array or properties that will have precedence over any properties set by rules. The only limitation of this system is that the callback function need to be synchronious. So long bash commands will cause Awesome to block until the result is parsed.

Is it possible to match clients based on properties other than class or instance?

Yes, but not directly. You need to create a new awful.rule that overrides the class property and then match that to your tag:

awful.rules.rules = {
--default stuff here,
{
    rule = { class = "URxvt", name = "dev"  },
    callback = function(c)
        c.overwrite_class = "urxvt:dev"
    end
}
}

This example changes the class of URxvt with name "dev" from "urxvt" to "urxvt:dev" which then can be matched to a tag.

For more information on possible properties look at Awful Rules or API

What is Tyrannical license?

Tyrannical is licensed under the 2 clause BSD

tyrannical's People

Contributors

arkanosis avatar blueyed avatar ch3sh1r avatar cherti avatar elv13 avatar freehaha avatar getzze avatar gotno avatar jaseg avatar junipergold avatar mpaulucci avatar ncoder-1 avatar radi-ka avatar sammyshp avatar sarumont avatar smaslovski avatar streetturtle avatar tomoyat1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tyrannical's Issues

Add configurable defaults for all options

After a conversation on IRC yesterday I came to the conclusion that the default value for many settings (usually nil or false), may not fit some non-insane workflows. Therefor, being to configure defaults for init, volatile and some other may be a very good thing after all.

This will break the API as settings.default_layout will turn into settings.tag.default.layout or something like that.

Undesired behaviour with predefined shortcuts

Hello,

recently I noticed that there are the predefined shortcuts in shortcuts.lua and started using them. In my rc.conf I have an tyrannical rule to add all terminals to one tag:

tyrannical.tags = {
    {
        name        = "term",
        init        = true, 
        exclusive   = true,
        class       = { "xterm", "urxvt", "URxvt", "XTerm" }
    },
...

Now I tried using the term_in_current_tag() and new_tag_with_term() functions. Unfortunately all terms will be moved to the "term" tag. I tried to prevent this behaviour in the term_in_current_tag() function with following statement:

local function term_in_current_tag()
    local s = capi.client.focus and capi.client.focus.screen or capi.mouse.screen
    local t = aw_tag.selected(s)
    if not t then return end
    aw_util.spawn(terminal,{intrusive=true,slave=true,tag=t})
end

But it doesn't working. Can you help here?

Thank you!

[enh] let enumerating tags

Hello.

First of all I'm sorry. I not familliar with lua enough, because awesome wm + tyrranical almost in standard config suits me almost perfect.

I suggest to add support for enumerating existing and new tags by this rule:

all tags names generated like this "index:name", where index is number which you should press in conjuction with modkey to select desired tag (i.e. modkey + 7), so we can have something like this: 1:term 2:im 3:www.

Here is scenario. Let's say I have setup mentioned before (3 tags - term, im and www present).Then let's say i insert a thumbdrive which causes pcmanfm to rise with contents of that drive, wich in turn causes awesome [through tyrannical] to create tag files. in proposed enhancement it would result to appear 4:files so i easily can switch between tags in 1 step

As a variation - numbers can appears only when user presses modkey or something along those lines.

My suggestion in poorely written code looks like this

  • wrapper-function for adding tag:
 local function add_tag(params)
   local index, name, tag = unpack(params)
   awful.tag.add(index .. ':' .. name, tag)
   return index+1
 end

plus something like this for deleting tag with decreasing counter

  • add index somewhere in init
local index = 1
  • generic replacement all over tyrannical
- awful.tag.add(v.name,v)
+ index = add_tag(index, v.name, v)

Merge Tyrannical.spawn()

Allow tyrannical to replace awful.spawn. It will allow to spawn with a Tyrannical property array or a tag

    tyrannical.spawn("command",{
       tag=awful.tag.getidx(2),
       floating=true,
   }

This is possible since awesome 3.5.3

Fully working example rc.lua

Can You provide a fully working example rc.lua

I tried to use your sample, i remove all the usage of config and util modules.
Add on a default rc.lua, and all i got was a wm with no wibox.

`no_focus_stealing_out' does not do anything

Is no_focus_stealing_out implemented anywhere? I do not see it doing anything, contrary to what the documentation claims.

I do not focus clients by other means, i.e. awful.rules or anything like that.

Releases

Can you please tag commits here to create releases? It would be handful for those who want to use "stable" snapshot only.

howto force a client to a tag?

I'm trying to force a client to appear on a particular tag (e.g. when restarting awesome).

Here's what i tried:

awful.rules.rules = {
    -- All clients will match this rule.
    { rule = { },
      properties = { border_width = beautiful.border_width,
                     border_color = beautiful.border_normal,
                     focus = awful.client.focus.filter,
                     keys = clientkeys,
                     buttons = clientbuttons } },
    -- Set Firefox to always map on tags number 2 of screen 1.
    { rule = { class = "Iceweasel" },
      properties = { tag = awful.tag.gettags(mouse.screen)[3] },
    },
}

the problem with the corresponding (commented out) code in the example.rc.lua
is that there is no global variable "tags" that i can access.

The line awful.tag.gettags(mouse.screen)[3] seems not to to what i thought it
would. The client does however get caught by the rule.
Ideally, I could get the tag object by its name given in the mytags section.
How do i do that?
Thanks

Standard tag

Is it possible to add a standardtag, so that every client, wich does not mach any class property opens in that tag instead of creating a new one?

clone_on second monitor not working as expected

System

  • Proprietary NVidia drivers
  • Awesome 3.5.1
  • Tyrannical master
  • Ubuntu 13.04

I've created a tag
{
name = "WWW",
init = true,
exclusive = true,
screen = 1,
clone_on = 2,
layout = awful.layout.suit.max, -- Use the max layout
class = {
"Opera" , "Firefox" , "Rekonq" , "Dillo" , "Arora",
"Chromium" , "nightly" , "minefield", "chromium-browser" }
} ,

A new tag is listed on both monitors.
I open firefox on WWW Screen 1 and it's all good.
I switch monitor 1 to a diff tag.
Switch monitor 2 to WWW expecting to to match what I just saw on monitor 1, however either nothing is display, or the windows flickers away really fast.
Now monitor 2 has glitched out and created a second WWW tag. It is now the only tag which displays firefox.
Switching to WWW on monitor does not display firefox.

I will test this on a different machine, I wonder if it has to do with Nvidia TwinView or something. Cloning sounds like a killer feature I just haven't got it to work yet.

Update default rc.lua

It is outdated and does not have all the cool keybindings

Also update the README.md to show the keybindings with links to the rc.lua

Use SNID for exec_once

The current exec_once does not take into account the SNID for force a specific tag. A client can be launched in an arbitrary tag by accident

Urgent property is not working

Without tyrannical, when a client that is not focused receives a urgent bell, its tag becomes highlighted normally.
But when using tyrannical, the clients are not responding to the urgent bell signal anymore. Awful is managing a list of clients that received a urgent bell, but this list remains empty when tyrannical is loaded. I tried to reconnect the signal property::urgent to the clients without success.

I am using awesome 3.5.5

incorrect tags swaping between the screens

I'm trying to make XMonad-like dual screen behavior, so i set "screen = 1" and "clone_on = 2" for every tag. After chosing tag [1] on second screen, with opened tag [1] on first screen, it should swap the active tags between first and second screens, but it's not. Actually, first screen becames empty, and then, after some tag switchings on second screen it turns on some tags (i have no idea why, i'm working only with second screen)

Strange behavior with multiple exclusive tags for a class

The example rc.lua says:

exclusive   = true,                   -- Refuse any other type of clients (by classes)
class       = { --Accept the following classes, refuse everything else (because of "exclusive=true")

When I have two different tags with exclusive set to true, and the same 'class', I get some strange behavior.

For example:
I have two "term" tags, "term 1" and "term 2", one in screen 1, and the other in screen 2. Both are exclusive and have "terminator" as 'class' property.

When I open terminator on screen 1, it opens ok, but a clone of "term 1" is created on screen 1, called "term 2". When I call terminator on screen 2, the same happens: a tag "term 1" is created on screen 2, being a clone of "term 2".

Add a FAQ section to README.md

  • How to add/remove tag with keybindings (thanks sochotnicky)
  • How to emulate and absolute index
  • How to assign dynamic keybindings

[Awesome 3.6+] Port to the shared spawn::completed_with_payload signal API

The Tyrannical launcher (awful.spawn("dolphin", {floating=true, new_tag=true}) style commands) are now supported by upstream. Tyrannical would still have to implements the handler to support intrusive, new_tag and some others. However, it would make it simpler to extend exec_once and exec to support much cooler use case

    {
        name = "Develop",
        init        = true                                              ,
        exec_once   = {
            {"kate", {master=true, focus=true},
            {"urxvt -cd /", {slave=true}.
            {"urxvt -cd /home", {slave=true}.
            {"urxvt -cd ~/work/", {slave=true}.
            {"kcalc", {floating=true}}
        },
        exclusive   = true                                           ,
        icon        = utils.tools.invertedIconPath("bug.png")        ,
        layout      = awful.layout.suit.max                          ,
        class ={ 
            "Kate"          , "KDevelop"       , "Codeblocks", "Code::Blocks" , "DDD", "kate4"             }
    } ,

Here exec_once would launch 3 instances of urxvt in the Develop tag, even if urxvt is match other rules. This remove the need for ugly class override hacks. It also allow to properly setup a full tag layout from Tyrannical tag declaration.

Currently, I got an implementation of this, but it is unclean and break exec_once current behaviour

Request for ideas for Tyrannical 1.0

Hello all 13 peoples who subscribed to Tyrannical feed.

I plan to release 1.0 soon and would like your opinion and feedback. One thing that will go in for 1.0 is a list is proposed shortcuts. So far I have:

  • Add tag
  • Remove tag
  • Rename tag
  • Fork tags
  • Create a new tag with the current focused client
  • Create a new tag with the 2 last clients from history

Proposed bash/zsh rc functions:

echo "require('awful').util.spawn('urxvt -e \"kcalc\"',{new_tag=true})" | awesome-client

I also will link to the "Repetitive" module that implement the long requested feature to have keyboard shortcuts for tags and clients declared in Tyrannical rules:
https://github.com/Elv13/repetitive

A small set of bash/zsh alias to launch client from terminal with Tyrannical properties:

  • Intrusive
  • New tag
  • As floating
  • Sticky

The last item I plan to add is an implementation of exec_once that works with startup notifications and shell commands and maybe backport the improved launcher (mod4+r firefox + control enter to launch in a new tag) as the patch is kind of staled upstream.

Do you have any other cool ideas that?

Issues with New Modkey+R binding

I am having some trouble implementing the Modkey+R. Running awesome 3.5.6 arch linux 64bit. The prompt does not run when adding this feature. Link to my rc.lua.

Matching errors until restart

Hello there !

I have a curious behaviour with tyrannical and Spotify, I have a matching rule for Spotify but on start, it is never matched to any tag (Pops into a N/A tab) but if and only if I restart Awesome (without killing spotify) then it will be matched on the correct tag.

Here's my tag.lua file where all the magic happens and here is the xprop output for Spotify Spotify.prop.txt

     {
        name      = "media",
        layout    = awful.layout.suit.fair,
        exclusive = true,
        init      = false,
        volatile  = true,
        screen    = {1,2},
        class     = {"vlc", "spotify", "Spotify"}
    },

None tag is focused on startup

With the example rc.lua, none of the tags is focused on startup.

How can I achieve that?

It would be nice if there was an tag property to set which tag will be focused on startup (one per screen).

Awesome project, BTW! :)

Force screen issue

How can I forcefully move some class to specified screen/tag?
force_screen doesn't work for me, is there some unexpected/expected behavior?

107     {
108         name = "S",
109         init        = true,
110         exclusive   = true,
111         screen      = 1,
112         layout      = awful.layout.suit.tile,
113         selected    = true,
114         force_screen = 1, 
115         exec_once   = {"skype"}, --When the tag is accessed for the first time, execute this command
116         class  = {
117             "Skype",▓
118         }
119     } ,

tyrannical should not check lowercase by default

things like urxvt and xterm use the lowercase name as a custom parameter with the capitalized name being a common denominator.

for example doing the following urxvt -name someName opens a terminal with the classes

someName, URxvt

while the default urxvt classes are

urxvt, URxvt

if you now match urxvt on any of your workspaces it will automatically match someName as well even though the class doesn't exist.

In general this is done so that you can use your xresources in the following manner

URxvt* for all urxvt derivates so urxvt -name htop -e htop would match it as well in there you can set font sizes background colors etc.

urxvt* on the other hand would match urxvt -e htop but not urvxt -name htop in the xresources.

Tyrannical should follow the same convention or at least make it optional

Make clients keep their tags when restarting awesome

Hey o/,

I wasn't able to try my code with multiple screens, so i don't know if it will work, but here it is:

That's the code that loads the tags after awesome started :

local tyrannical

awful.client.property.persist("startup", "boolean")
awful.client.property.persist("disp", "string")

local tags = {}

if (#client.get() > 1 and client.get()[1].startup) then
    tyrannical = require("tyrannical")
else
    gears.timer.delayed_call(function() 
        tyrannical  = require("tyrannical")
        tyrannical.tags = tags.tags

        for _, c in ipairs(client.get()) do
            c:tags({c.screen.tags[11]})
        end
        for _, c in ipairs(client.get()) do
            disp = nil
            load("disp = " .. c.disp)()
            local ctags = {}
            for i, t in ipairs(disp.tags) do
                ctags[i] = c.screen.tags[t]
            end
            if(#ctags) then
                c:tags(ctags)
            end
        end
    end)
end

-- tags.tags definition

if (#client.get() > 1 and client.get()[1].startup) then
    tyrannical.tags = tags.tags
end

And this is a function to launch before awesome.restart to save client-tag matchings:

function()
    for _, c in ipairs(client.get()) do
        local screen = c.screen.index
        local ctags = {}
        for i, t in ipairs(c:tags()) do
            ctags[i] = t.index
        end
        c.disp = utils.serialise({screen = screen, tags = ctags})
    end
end

(and utils.serialise just comes from your repo Forgotten. I've copied and pasted the function into a utils.lua file and required it)

example how to get shifty's "positions" behaviour?

I saw that it is mentined in the README, but i cannot get this to work
(I'm really bad with lua)
Here is what i have atm, any hints are welcome.

mytags = {  --tag defs here 
    {
        name        = "web",
        mwfact      = 0.65,
        position    = 3, 
        init        = false,
    },
}
tyrannical.tags = mytags

function tag_by_pos(i)
    for i,tag in pairs(mytags) do
        if tag["position"] == i then
            return tag.name
        end
    end
end

I'm unsure how to use or test my new function tag_by_pos.

I tried

for i = 1, 9 do
    globalkeys = awful.util.table.join(globalkeys,
        awful.key({ modkey }, "#" .. i + 9,
                  function ()
                        local screen = mouse.screen
                        local tag = tyrannical.tags_by_name[tag_by_pos(i)]
                        ...

but pressing mod+3 triggers a naughty popup about a

failed attempt to index local _'tag' (a number vallue

in awful/tag.lua:533

Can't add class with a hyphen in the name to a tyrannical.properties. array

This throws an error:

tyrannical.properties.border_width  = {
    lxqt-panel =   0
}

but this works perfectly:

tyrannical.properties.border_width  = {
    XTerm =   0
}

"lxqt-panel" works just fine in other parts of Tyrannical where it's in quotations, but in these sections quotations don't work. I have also tried escaping it with % and %% with no luck

Add support for locked tags

Locked tag = all non floating+intrusive clients are rejected, even if they match. In the case of maching, a duplicate tag will be create.

New properties:

  • Locked (boolean)
  • Max_clients (number)

So the tag states are going to be

  • inclusive : Accept all clients
  • fallback : Accept client without better matches
  • exclusive : Reject all non-intrusive clients
  • locked : Reject all clients but intrusive+floating ones

Tags not in order

Tags does not respect the position index.
If tag A with position = 2 is created after tag B with position = 3, it will get position 3.

Class name matching problem

I have this tag setup:
{
name = "5:IDE",
position = 5,
exclusive = true,
init = false,
floating = false,
layout = awful.layout.suit.max,
class = { "jetbrains-idea-ce", "jetbrains-idea", "jetbrains%-idea%-ce%"}
},

"jetbrains-idea" works fine. However, this one is not matched: WM_CLASS(STRING) = "sun-awt-X11-XFramePeer", "jetbrains-idea-ce"

Even weirder, new dialog boxes from "jetbrains-idea-ce" are picked up on IDE:5 as expected.

Any thoughts?

Thanks!

fancy prompt from the FAQ doesn't work

Hi!

I tried to replace

awful.key({ modkey },            "r",     function () mypromptbox[mouse.screen]:run() end),

with your fancy code suggested in the README.
Its not working, not even in the example.rc.lua.

I'm on awesome 3.5.6 (stable) from tarball, just ompiled.
Any ideas?

bad argument #2 to 'add_signal'

Hello,

the last few days I wanted to switch from shifty to tyrannical. So I tried it out and got the following error with the example.rc.lua:
tyrannical/init.lua:22: bad argument #2 to 'add_signal' (function expected,
got no value)

Obviously the function add_signal in line 22 has no second argument. But I couldn't figure out, how to solve the problem in good manner.

I'm using Debian Wheezy:
Awesome 3.4.13-1 with liblua5.1-0

The description on the shifty page of the awesome wiki and the readme here didn't say, that tyrannical is not working with 3.4.13. That's right?

Thanks for your help!

Greetins,
bastorran

Match client when send to screen

I use two screens, and I have to switch clients from one screen to the other. However, when the client is sent to the other screen, it goes to the opened tag there. I would like the client to go tha tag matched by tyrannical.
This can be done by making the match_client function of tyrannical part of the API. In init.lua:

module.match_client = match_client

Then for my shortcut (Win+F5 in my case) I set:

awful.key({ modkey,           }, "F5",     function (c) c.maximized=false awful.client.movetoscreen(c) tyrannical.match_client(c) c.maximized=true end,  "Move to other screen")

exec_once exec'ing more than once

I imagine this could easily be user error, but I've got just a slightly edited version of the included example config. I've added an exec_once {"google-chrome-stable"} to my 'Internet' tag.

Visiting the tag for the first time works as expected, spawning a Chrome instance. However, switching away and back to the Internet tag spawns another instance.

Is there an issue here, or am I doing something stupid? Config attached.
rc.lua.txt

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.