Results 1 to 10 of 83

Thread: HOWTO: Automating Gnome with Devil's Pie

Threaded View

  1. #1
    Join Date
    Mar 2005
    Location
    Freiburg/Germany
    Beans
    653
    Distro
    Ubuntu 7.10 Gutsy Gibbon

    HOWTO: Automating Gnome with Devil's Pie

    Disclaimer: This is quite long, I'm sorry, but I tried to be detailed. I'm open for all suggestions and criticisms and would be happy to hear them. Thank you.

    Note: This howto is intended for Devil's Pie 0.10, the one included with breezy. I do not know whether it will work with older versions, and the newest use a different method for configuration. A short introduction to the new format follows at the end.

    Introduction

    Gnome is a desktop environment that is - in my opinion - quite pleasant to use. But sometimes a user hits the limits of what is possible with plain Gnome. For example, a user who has developed a setup of applications on workspaces has to move the windows manually; there is no way to tell standard Gnome to - for example - always open Evolution on the second workspace, or Firefox always maximized, to have Gaim converstaions on all workspaces, to fix applications that always start in the wrong position and too small a window, and so on.
    Users who want such functionality need not worry, it is possible to add this - and much , much more - with a little, but powerful application called Devil's Pie. The problem is that its configuration is quite technical and can be confusing. I will try to make this a little more transparent.

    Part I: The Basics

    Installation

    Installation of Devil's Pie is quite easy; you can just use synaptic. Make sure you have universe enabled (https://wiki.ubuntu.com/AddingRepositoriesHowto). If you want to do it from a command line, "sudo apt-get install devilspie".
    After installation, you will probably want to add it to your autostart. Open System -> Preferences -> Session, go to the startup programs tab, Add. Enter "devilspie" into the command field, and set the order to something low.
    Devil's Pie by default reads its configuration from a hidden file called .devilspie.xml that you have to create. Open gEdit (or your favorite other text editor) and save a new document as ".devilspie.xml".


    Basic setup of the configuration file


    Now, lets start populating the configuration file. It is in XML so it might look confusing, especially to people not used to programming or XML. You'll get used to it, it looks by far harder than it is.
    Devil's Pie uses a set of rules (called "flurbs"... I didn't name it, don't blame me :)) to determine what it should do with windows. If there is no rule for a window, it will do nothing, so if you have no flurbs it will just behave like normal gnome. The Structure is like this:

    Code:
    <?xml version="1.0"?>
    <!DOCTYPE devilspie SYSTEM "devilspie.dtd">
    <devilspie>
    <!-- replace this lines with your flurbs -->
    </devilspie>
    So start by pasting this in your (still empty) configuration file.

    Flurbs

    OK, now it's time to talk in more details about flurbs. Like I already said, flurbs are rules. At the beginning I gave the example of automatically moving Evolution to your second workspace. How to formulate this as a rule? "If a window is called Evolution -> Move it to Workspace number two". A little more abstract: "If a window fits (criteria) -> Do (actions)". And finally, in a way that Devil's Pie can understand:

    Code:
    <flurb>
        <matchers>
            <!-- replace this with your criteria -->
        </matchers>
        <actions>
            <!-- replace this with your actions -->
        </actions>
    </flurb>
    Note especially that you can have several of each in one flurb: For example, its possible to not only move Evolution to Workspace 2, but also maximize it at the same time.
    Let's continue to implement moving Evolution as a flurb.

    Matchers

    Explaining matchers in more detail is something I'd like to hold for later, As for a good explanation I'd have to go into some details. For our example, I just give you a ready-made matcher and you'll understand later how it works exactly.

    Code:
    <matcher name="DevilsPieMatcherWindowName">
        <property name="window-title" value="Evolution"/>
    </matcher>
    Actions

    Now, Devil's Pie is quite powerful and can do a lot. Again, I'll give you a reference and some more details later. This action moves Evolution:

    <action name="DevilsPieActionSetWorkspace">
    <property name="workspace_index" value="2"/>
    </action>

    Putting it together

    How does this look like when it's put together? Try it.

    If you've understood the structure so far, you should arrive somewhere near this:

    Code:
    <?xml version="1.0"?>
    <!DOCTYPE devilspie SYSTEM "devilspie.dtd">
    <devilspie>
      <flurb>
        <matchers>
          <matcher name="DevilsPieMatcherWindowName">
            <property name="application_name" value="evolution"/>
          </matcher>
        </matchers>
        <actions>
          <action name="DevilsPieActionSetWorkspace">
            <property name="workspace_index" value="2"/>
          </action>
        </actions>
      </flurb>
    </devilspie>
    If your version is different, take another look to see if you understand how i arrived at this. If you still don't, send me angry PMs that my Howtos are too hard to understand :) (oh and include what and why you didn't understand it so that I can try to fix that^^;; ).

    Let's get away from dry theory for a bit and try it out! Save the above as your .devilspie.xml, (re)start Devil's Pie. and start Evolution. It should now open on your second workspace :)

    Note that after editing the configuration file, devilspie needs to be restarted for the changes to take effect if it's already running, so "killall devilspie" followed by "devilspie &" will make sure that you're using the new version.

    If you managed to get this far, give yourself a pat on the back and celebrate a little. You've taken the first step to become a Devil's Pie master. Continue reading when you feel up for the next step.

    Part 2: More on Matchers

    As promised, here's more about Matchers. Let's start with another example.
    With Hoary, a lot of users complained that they were missing IMs, because gaim did not sufficiently alert them that they got a message. In Breezy, the application glows in the task list if it wants to alert the user. But what if you're on another workspace? Unless you have a global task bar, you won't see the notification. The solution is of course to make your conversation window sticky on all desktops. Let's see if we can get Devil's Pie to do that for us.

    We're covering more on actions later, here's what we need for this flurb:
    Code:
        <actions>
          <action name="DevilsPieActionSetWorkspace">
            <property name="pinned" value="TRUE"/>
          </action>
        </actions>
    Time to look at the matcher part of our flurb. As we've seen, it starts with <matchers> and ends with </matchers>. Our last flurb then had a line "<matcher name="DevilsPieMatcherWindowName">" This tells Devil's Pie which matcher to use.
    There are two you can choose here: DevilsPieMatcherWindowName, which we've already seen in action, and DevilsPieMatcherAlways.

    DevilsPieMatcherAlways

    This one simply matches every window :) Thus it doesn't need any further arguments; If you want to match all windows the following is a complete matchers part:
    Code:
    <matchers>
         <matcher name="DevilsPieMatcherAlways"/>
    </matchers>
    Since DevilsPieMatcherAlways does not have any properties you do not need to close it by a seperate tag, but can instead add a slash before the end of the tag. The above is equivalent to
    Code:
    <matchers>
         <matcher name="DevilsPieMatcherAlways">
         </matcher>
    </matchers>
    I will occasionally use this shorter notation in this guide, but you can also keep the longer version.


    DevilsPieMatcherWindowName

    This is a bit more interesting. This will allow us to match windows based on more specific criteria. Of course, this means we have to tell Devil's Pie what these criteria are :) In our first example, we did this with the line "<property name="application_name" value="Evolution"/>". This is a structure we will see again later; we specify a property and a value for that property. For DevilsPieMatcherWindowName, we have 3 different properties we can use: window-title, application-name and window-role. window-title and application-name explain themselves, one matches the window title (what you see in the title-bar), the other the application name. window-role is more hard to explain, and not all windows have this property. It's what role a window fills, if that makes sense.

    What values can we pass to these properties? If you know about "regular expressions", good for you, you can use regexps. If not, explaining them would by far break the limits of this (much too long) Howto. A simple version: If you set "xyz", the matcher will accept everything that contains "xyz". So, caution: if you match "gaim" by window_title, this will also accept other windows that contain "gaim" in their name, like firefox on certain websites.

    So, this would match all Gaim windows:
    Code:
    <matchers>
      <matcher name="DevilsPieMatcherWindowName">
        <property name="application_name" value="gaim"/>
      </matcher>
    </matchers>
    We're not done yet, this would also apply to the buddy list window, and we only want to pin the conversations. Gaim is nice and sets window roles; IM windows have the role "conversation". So this is the .devilspie.xml that contains our first flurb and a solution for our current example:

    Code:
    <?xml version="1.0"?>
    <!DOCTYPE devilspie SYSTEM "devilspie.dtd">
    <devilspie>
      <flurb>
        <matchers>
          <matcher name="DevilsPieMatcherWindowName">
            <property name="application_name" value="Evolution"/>
          </matcher>
        </matchers>
        <actions>
          <action name="DevilsPieActionSetWorkspace">
            <property name="workspace_index" value="2"/>
          </action>
        </actions>
      </flurb>
      <flurb>
        <matchers>
          <matcher name="DevilsPieMatcherWindowName">
            <property name="application_name" value="gaim"/>
            <property name="window_role" value="conversation"/>
          </matcher>
        </matchers>
        <actions>
          <action name="DevilsPieActionSetWorkspace">
            <property name="pinned" value="TRUE"/>
          </action>
        </actions>
      </flurb>
    </devilspie>
    Finding the right values

    I didn't tell you yet how to find out what window_title, application_name and window_role a certain window has. This can be a bit messy, as some applications don't play nice here.
    It's easy for window_title, since you can just read that in the title bar. Now for the other two...
    First a way that often works: Execute
    Code:
    xprop | egrep "(WM_WINDOW_ROLE)|(WM_CLASS)"
    in a terminal. Your mouse pointer will become a crosshair. Click on a window you want to know more about, and you will get an output like:

    WM_WINDOW_ROLE(STRING) = "conversation"
    WM_CLASS(STRING) = "gaim", "Gaim"

    The WM_WINDOW_ROLE(STRING) specified here is the window_role for Devil's Pie; if it doesn't output that line the window does not have a window_role. The first part of the WM_CLASS(STRING) line (in this case "gaim") is sometimes, but by far not always the application_name. Some exceptions are, for example, gnome-terminal and nautilus. Sometimes you can guess the right application_name, sometimes not.
    The definitive way to find out the application name is enabling the debug flurb and starting Devil's Pie from the command line, it will tell you the window-title, application-name and window-role of each existing window and each new one you open. Save the following as ".devilspie-debug.xml".
    Code:
    <?xml version="1.0"?>
    <!DOCTYPE devilspie SYSTEM "devilspie.dtd">
    <devilspie>
      <flurb name="Print Window Names">
        <matchers>
          <matcher name="DevilsPieMatcherAlways"/>
        </matchers>
        <actions>
          <action name="DevilsPieActionDebug"/>
        </actions>
      </flurb>
    </devilspie>
    Start devilspie with "devilspie .devilspie-debug.xml". It will output the relevant information for all windows, close it with <ctrl>-<c> afterwards. You should then be able to find out (sometimes with a little creativity ^^;; ) how to match those windows. (If there's a better way to find out the application_name, please tell me and I'll update this).

    (Hint: gnome-terminal sets it's window_role as "gnome-terminal-<lots of confusing numbers>", so match window_role against "gnome-terminal" to get all gnome-terminal windows)

    OK, that's enough (I hope) about one side of the rules, next let's look at the cool things we can do on the other side.

    Part 3: Actions

    Taking one of the examples, we see that the actions Part looks quite similar to the matchers.

    Code:
    <actions>
       <action name="DevilsPieActionSetWorkspace">
         <property name="pinned" value="TRUE"/>
       </action>
    </actions>
    Again, we choose something, then set values to it's properties. If you want to set the "abc" property of a action type "zyx" to "uvw", you do it like this:

    Code:
    <actions>
       <action name="zyx">
         <property name="abc" value="uvw"/>
       </action>
    </actions>
    Here's a list of action types: DevilsPieActionHide, DevilsPieActionDecorate, DevilsPieActionLayer, DevilsPieActionSaveGeometry, DevilsPieActionSetGeometry, DevilsPieActionSetWorkspace, DevilsPieActionResize, DevilsPieActionDebug, DevilsPieActionSetWintype, and DevilsPieActionOpacity.

    Remember: you only have to set Actions if you actually want to change something, otherwise just leave them out.

    DevilsPieActionHide is for hiding windows from the task list or the workspace switcher, with "skip-tasklist" and "skip-pager", respectively. Both take either "TRUE" or "FALSE" as values.
    DevilsPieActionDecorate is for setting or hiding window decorations (meaning title bars usually). Set "decorated" to "TRUE" or "FALSE".
    DevilsPieActionLayer is for setting a window as on top of all other windows, with "above" as "TRUE" or "FALSE" again.
    DevilsPieActionSaveGeometry is for... um... it prints out lots of stuff if you move or resize that window, I didn't find out what else it does yet. It does not seem to remember the size of applications and then restore them to that size, at least not for the programs I've tried. Has no properties either.
    DevilsPieActionSetGeometry on the other hand is quite useful, it allows you to set window positions and size. Like for Evince, which always opens too small. Has "xoffset", "yoffset". "width" and "height" properties that take numbers. First two set distance from the left and top border, respectively, to the top left corner of the application window, the other sets the size.
    DevilsPieActionSetWorkspace, well you know this one from the two examples in Part 1 and Part 2. "pinned" as "TRUE" or "FALSE", "workspace-index" as a number.
    DevilsPieActionResize is used to resize windows, but unlike the previous not by giving numbers for the size. Properties "maximized", "maximized-horizontally", "maximized-vertically", "minimized", "fullscreen", all take "TRUE" or "FALSE".
    DevilsPieActionDebug has no properties and enables the debug mode, it will print window_title, application_name and window_role of all the open windows.
    DevilsPieActionSetWintype does something I don't know ^^;;
    DevilsPieActionOpacity requires xcompmgr active (read the great howto here: http://ubuntuforums.org/showthread.php?t=75527). It allows you to set the translucency of windows (similar to transset, only automatically :)). Property "opacity", takes a value from 0.00 (completely translucent) to 1.00 (completely opaque)

    As you see, the possibilities are nearly endless.

    The complete Devil's Pie reference is available here (if you have it installed): file:///usr/share/doc/devilspie/devilspie-reference.html


    Thanks go to Ross Burton for writing such a cool program (check out his site at http://www.burtonini.com/), the Ubuntu team for creating such a fine distribution and community, and to those who actually read this for enduring my by far too long howto :)

    Appendix: Devil's Pie 0.13+

    Starting with Devil's Pie 0.13, a new method for configuration, called "S-Expressions" is used. Currently this is only relevant for people who are using Dapper, or who have compiled the new version themselves. Many of the old concepts still apply, so I assume you have read my explanation of how to use the old Devil's Pie versions. I didn't really test this part of the guide as much as I should; so if something doesn't work, it's probably my error. Drop me a note and I'll take a look at it.

    New Devil's Pie releases read their configuration from "rulename.ds" files, which may be located in ~/.devilspie/ and /etc/devilspie, the last one is for rules that apply to all users. Currently, each .ds file can only contain a single rule, so don't try to put more than one in each file.

    Note: Things in UPPER CASE are placeholders, you have to replace them with a real value. They're only here to make the structure more obvious. Bolded things are part of the expressions (it's a bit hard to see, i notice now... this includes (, ), + and x, but not the *).

    A Rule looks like this:
    (RULE)

    Where RULE can be one of the following:
    - ACTIONS
    - if (MATCHERS) (ACTIONS)

    The first one is for rules that apply to all windows, the second one is for rules that apply only to certain windows. As in the main guide, let's look at matchers first.

    MATCHERS can be the following:
    - is (TYPE) VALUE
    - contains (TYPE) VALUE
    - matches (TYPE) VALUE

    TYPE can be one of application_name, window_name and window_role, they're the same as in previous versions, with the exception that window_title is now called window_name.
    VALUE is something double-quoted, this is the value you want the windows to be compared against.
    is looks whether the appropriate value for TYPE is the same as your VALUE, contains whether it contains your VALUE, and matches is used if you want Regular Expressions (which I won't explain this time either ^^;;; , look it up on the internet if you're interested)
    So this would be a MATCHERS that gets all the windows that have an a in their title: contains (window_name) "a"

    Now, this is not terribly interesting yet... just checking for one attribute often isnt enough. What if I want all Firefox windows that have "Ubuntu" in their title? You have to combine matchers. In addition to the above,

    MATCHERS can also be: (* means that you can have as many as you want)
    - and (MATCHERS)*
    - or (MATCHERS)*

    And checks whether all of the matchers following it are true, or checks whether at least one of them is true. So this MATCHERS would get all Firefox windows with Ubuntu in their title:
    and (is (application_name) "Firefox") (contains (window_name) "Ubuntu")

    You can combine these elements as you want it. The only limit is your imagination :)

    Now for the actions...
    ACTIONS can be
    - ACTION
    - begin ACTION*

    quite simple, really: If you have more than one action, start with a begin. Some actions have arguments, put the action name and arguments in parens (like I did below) unless you only have one action, when you can (and have to) leave them away. Here's a of the different ACTION types:

    debug
    - Display window information (if you start devilspie from the command line)
    (geometry WIDTHxHEIGHT+XPOSITION+YPOSITION)
    - Set size and position. So (geometry 100x100+0+0) will make it 100 by 100 pixels large and put it into the top right corner
    fullscreen
    - Make the window full screen
    maximize
    - Maximize the window
    maximize_vertically
    - Maximize the window vertically
    maximize_horizontally
    - Maximize the window horizontally
    minimize
    - Minimize the window
    shade
    - Roll the window up
    unshade
    - Roll the window down
    pin
    - Put the window on all workspaces
    unpin
    - Don't put the window on all workspaces
    (set_workspace NUMBER)
    - Move the window to that workspace
    skip_pager
    - Hide window from the Workspace Selector
    skip_tasklist
    - Hide window from the Window List
    above
    - Keep window above all other windows
    below
    - Keep window below all other windows

    undecorate
    - Remove border and title bar
    (wintype WINDOW_TYPE)
    - Set the window type to WINDOW_TYPE

    That's pretty much it for this short guide. Here are the examples from the main How-To as S-Expressions:
    Code:
     (if (and (contains (application_name) "evolution") (contains (window_name) "Mail")) (set_workspace 2)
     
     (if (and (contains (application_name) "gaim") (contains (window_role) "conversation")) (pin)
    And one last bonus tip: gedit can highlight matching brackets. Activating that feature makes creating and fixing complicated rules quite a bit easier. :)
    Last edited by Wolki; December 4th, 2005 at 01:26 PM.

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •