现在的位置: 首页 > 综合 > 正文

Building a Better Window Manager

2011年02月13日 ⁄ 综合 ⁄ 共 11919字 ⁄ 字号 评论关闭

Building a Better Window Manager

这篇文章,对于怎样跳出惯性思维,理解并定制自己的WM,我觉得这篇文章有不错的意见。

Building a Better Window Manager

Eric Mangold
teratorn (at) world (dash) net (dot) net

December 21, 2003

Contents

1 Purpose
2 Mindset
3 Mice Are Slow
4 The Keymap
5 Choose a Window Manager
     5.1 Configuring the Window Manager
     5.2 Launching Programs
     5.3 General Bindings
     5.4 Other bindings
     5.5 Application specific key translation
6 Conclusion
7 Links

1   Purpose

This paper deals with software user interfaces, and primarily with the user interface of window managers1, or WM's. It is the author's opinion that there is a lot of software with poor user interface capabilities. Also, that software with good interface capabilities is almost always in need of fine-tuning.

Thus it is the purpose of this paper to describe a good window manager interface. One that will minimize wasted time, and providing the user with a more streamlined interface experience. Better concentration should also be achievable while using your computer as opposed to the default interface of most WM's.

This paper is aimed at people who havn't thought much about customizing their environment. However, it's the author's hope that even highly advanced users will find something useful.

2   Mindset

When you're using your computer you should always be aware of what you want to do, not just how you currently do it. For example, when you want to switch to a certain running application, you might reach for the moues to click it in a task bar, or hit Alt-tab to cycle through your windows. Never automatically assume that your current tools are the best, and in this case they commonly are not. In this way you can identify faster ways of doing things.

3   Mice Are Slow

Firstly, if you don't know touch-typing then this tutorial will be of little use. If you need to, go learn touch-typing first then come back here.

It should be obvious that using the mouse to click a button, for example, is painfully slow compared to pushing a key or key-combination. All too often will software rely on the mouse where good key bindings2 would be better.

It wouldn't hurt to develop a healthy disdain for mouse-ware3 and the overuse of mice in general.

4   The Keymap

This section describes how to change what your physical keys do. You might not want to do this since it will make your keyboard work differently than other peoples. This is more or less of an issue depending on how frequently you use other "uncustomizable" computers.

We are going to set up the modifier keys. A modifier is a key you press only in conjunction with other keys.4 C-c and C-v are common bindings for "copy" and "paste" and illustrate the use of modifiers. Please note that modifiers are slower that just pushing most keys. You should always prefer to not use modifiers if just pushing a key will work for a given application. Awkward keys such as Home and End are an exception. These keys are too hard to push and should never be used. Use standard emacs bindings instead.5

I'll describe two modifier layouts. The first is the one that I use. The 2nd is one that you might find more desireable.

The first thing we will do is setup the "Control" and "Alt" keys as the two physical keys just to the left of the space-bar. The two physical keys just to the right of the space-bar will be our "Super" and "Hyper" keys. This will give names to the keys so we can use them in XFree86.

The physical layout will look like this.

[ Control_L ][ Alt_L ][      space      ][ Super_R ][ Hyper_R ]

As you can see, all we care about are the two keys on either side of the space-bar, whichever keys they may be. In case you've never thought about it, you press Alt_L and Super_R with your left and right-hand thumbs, respectively.

The reason we do this is to have a number of modifiers that are easy to push that we can use to control things. Control and Alt (meta) will have application-specific uses. Super will manipulate windows and the window manager environment (mostly). Hyper will launch the programs we use (mostly). I find that I can do everything I need with these four modifiers. If you find yourself wanting another modifier for something, the right-hand Shift key would probably be a good choice.

OK, to get XFree86 to do this you need to edit ~/.Xmodmap. You may also use the xkeycaps tool. Since I don't know your current keymap, I'll give you a procedure that should work regardless. It may be more detailed than necessary.

Step 1. Open a terminal and run the command "xev". Now push the 2nd key to the left of the space-bar (the one we want to make Control_L). Write down the keycode. Repeat for the 1st key to the left of the space-bar, then the 1st on the right, then the 2nd on the right. You have the four keycodes now.

Step 2. Make a backup copy of ~/.Xmodmap, if it exists, then open ~/.Xmodmap in a text editor. Copy and paste the follow block of lines:

keycode a = Control_L
keycode b = Alt_L
keycode c = Super_R
keycode d = Hyper_R
clear control
add control = Control_L
clear mod1
add mod1 = Alt_L
clear mod3
add mod3 = Super_R
clear mod4
add mod4 = Hyper_R

Now, replace the "a" with the first keycode you wrote down, then replace "b" with the 2nd, and so on.

Next, we will swap the Escape and Caps Lock keys. Since Escape is pushed much more frequently than Caps Lock, it makes sense to have it in an easier to reach place. This is an even greater improvement if you use one of the vi-style editors. If you're on a standard US keyboard, then add the following lines to your ~/.Xmodmap file, otherwise you're on your own :).

keycode 66 = Escape
keycode 9 = Caps_Lock

Alternate #1 - Instead of the 2nd key left of the space acting as the Control key, have it act as the Escape key, and have the CapsLock key act as Control. You will have to experiment to determine if your useage patterns make this a better layout.

Finally, you need to ensure that your system is loading your ~/.Xmodmap file when you start XFree86. The easiest way to check is to reboot and/or restart X. Then open a terminal and run "xmodmap". You should see output that matches what we have configured above. If not, you need to set xmodmap to load ~/.Xmodmap manually. If you use the ~/.xinitrc or ~/.xsession files, then you can add the line "xmodmap ~/.Xmodmap" before your WM is launched. If you are using a graphical login, then you need to find it's startup file, and put the aforementioned line there.

5   Choose a Window Manager

I recommend sawfish. Other WM's may work, but I'm unware of any that have all the features that I will illustrate. You may also use sawfish with gnome (I do) if you want "visual representation of the desktop state", such as a task bar and those micro-windows for each virtual desktop. Of course we won't be clicking on any of those things, but they are useful for keeping track of the stuff that's running on your system. Gnome's also useful if you want a clock or panel applets or such.

5.1   Configuring the Window Manager

I'll detail my current sawfish config. You can adapt this to any window manager that supports the requisit features (if there are any). If you do, I would be interested to know which WM you chose and what features made it a good choice.

There are several groups of tasks that your window manager will handle. I will talk about each individually.

5.2   Launching Programs

A major task of the window manager is to launch programs for you. Another overlapping task is switching to programs that are already running. We are going to combine both tasks using the same key binding. This will not work for programs that you run more than once simultaniously. Your terminal emulator will probably be one of those.

So, for example, lets say Hyper-e is associated with your editor. If you press H-e while the editor is not running then it will be launched. If it is already running then it will be brought to focus (switching to the correct virtual desktop first).

This is a powerful mechanism and will save you keeping track of what is running and what isn't. We will use a sawfish extension called jump-or-exec to do this. Get it here http://sawfish.uberstyle.net/index.php/SawfishWiki/JumpOrExec and install it.

We are going to use the Hyper key to launch all the programs that we use. For each program that you want to use with jump-or-exec you need to add a block of code like the following to your ~/.sawfish/rc file.

(bind-keys global-keymap
    "H-e" `(jump-or-exec "GVIM"
        ,(lambda ()
           (system
            "gvim &"))
        ,(lambda (wind)
           (display-window wind))))

There are three main parts. The first "H-e" is the key combination we are binding here. "GVIM" is all or part of the window title of the program. "gvim &" is the command to run if a window matching the pattern "GVIM" is not found. Note the trailing ampersand. Without it the program will run in the foreground and block sawfish effectively hanging your X session.

For programs that you run more than once you can use the sawfish keybinding editor.6 Use the "Run shell command" function.

The bindings you choose aren't that important. Typically one will use the first letter of the programs name or it's function (such as "e" for "editor"). If such a letter isn't free to use, just pick one that's easy to press.

5.3   General Bindings

I'll just give you the bindings I use. Maybey a different configuration will suit you. The only rule of thumb is to make the most common bindings the ones that are easiest to press. Please note these are just the basics, and there are a lot more possibilities. For example, you could use sawfish to control XMMS.7

Super-a   -   Activate workspace: 1
Super-s   -   Activate workspace: 2
Super-d   -   Activate workspace: 3
Super-f   -   Activate workspace: 4
Super-m   -   Maximize window toggle
Super-x   -   Delete window safely
Super-j   -   Cycle windows
Super-k   -   Cycle windows backwards
Super-h   -   Previous workspace
Super-l   -   Next workspace
Super-o   -   Send to next workspace
Super-i   -   Send to previous workspace
Super-r   -   Run shell command: gmrun
Super-q   -   Popup window menu
Super-t   -   Popup root menu
Super-p   -   Iconify window
Super-e   -   Show errors
Super-u   -   Gnome logout
Super-w   -   Move window interactively
Hyper-t   -   Runs my terminal emulator

5.4   Other bindings

lookup.jl provides a mechanism to do some nifty things that I find myself doing every day. You can read all about it here http://www.ewanmellor.org.uk/sawfish.html . Here's the lisp I use for these bindings, but you may want something different.

(bind-keys global-keymap
    ; prompt for google search terms - focus browser window
    "Super-g" '(lookup "google" t nil)

    ; use X selection as google search terms - focus browser window
    ; (if selection contains a URL, then that URL is visited instead
    ; of searching google)
    "Super-G" '(lookup "google" t t)

    ; The next two are the same as the previous two
    ; except that they don't focus the browser window
    "H-g" '(lookup "google" nil nil)
    "H-G" '(lookup "google" nil t)

    ; dictionary searches
    "Super-c" '(lookup "dict" t nil)
    "Super-C" '(lookup "dict" t t)

    ; thesaurus searches
    "Super-v" '(lookup "thes" t nil)
    "Super-V" '(lookup "thes" t t))

5.5   Application specific key translation

This section deals with improving upon an applications keyboard interface where such application does not provide a way to do so "natively". An example will make this clear. X-Chat, an excellent IRC client, brings up the Search dialog box when you press the C-f binding. Some folks may prefer this, but I would prefer C-f to move the cursor forward one space in keeping with the other emacs bindings.8

With a bit of lisp code, sawfish can pull some tricks to make the program interface the way we want it to. In this case, we will catch the C-f event and synthesizing a Right (arrow) event thus producing the desired effect.

To do this, we will first add the following block of code to the ~/.sawfish/rc file.9

(define-match-window-setter 'keymap-trans
   (lambda (w prop value)
     (declare (unused prop))
     (let ((keymap (or (window-get w 'keymap)
                       (window-put w 'keymap (copy-sequence window-keymap)))))
       (mapcar
        (lambda (pair)          ; pair of from and to keys
          (bind-keys
           keymap (car pair)
           (lambda () (interactive)
             (synthesize-event (lookup-event (cadr pair)) (input-focus)))))
        value))))

Now add a block like the following for each program you want to "fix".

(add-window-matcher 'WM_CLASS "Xchat"
                     '(keymap-trans . (("C-f" "Right") ("C-s" "C-f"))))

There are three parts you should understand. The first is the symbol WM_CLASS, which indicates the following string will match against the class of the window.10 If you would rather match the window's title, use WM_NAME instead.

Next is the string "Xchat". It selects the window(s) that our key translations will apply to. We use this so that our translations will only affect the desired window(s). You can get the class string by using the "Matched Windows" configurator.11 If you are matching the window title instead, then just pick a unique part of the title string (it doesn't have to be the whole thing).

The third is the list of key events to translate. In the example above, that is the part of the code which reads (("C-f" "Right") ("C-s" "C-f")). It is simply a list of one or more pairs. Each pair specifies the "from" and "to" events for each translation.

Here is another example for Opera users.

(add-window-matcher 'WM_CLASS "opera"
                     '(keymap-trans . (("M-f" "C-Right") ("M-b" "C-Left"))))

This overrides the hard-wired shortcuts for the File (M-f) and Bookmark (M-b) menus. The bindings are then translated to C-Right and C-Left, respectively. This makes them move the cursor forwards and backwards by a word at a time. Emacs users should appreciate the added consistency.

6   Conclusion

Sawfish has a ton more possible bindings. I'm sure you will want to review them and locate any that will make your work faster. Also of note is the "Library" at the sawfish wiki where you can find (and contribute!) extensions that make it work in new and (hopefully!) better ways.

Please email me with any suggestions, criticisms or other ideas.

7   Links

抱歉!评论已关闭.