Thursday, March 28, 2013

Switch window by name on Linux - alternative to Alt+Tab

Today I want to share a very simple script that works with most Linux window managers: switch window by name.
It works like this: you press Ctrl+Alt+M, then a dialog appears where you write part of the name of the window, and you'll get switched to the window that matches the provided name.The string your provide will match part of window names in case-insensitive mode.
That means if you have "Foo - Mozilla Firefox" and type in "fire" you'll switch to firefox.

Note: it probably doesn't work with your configuration of awesome wm due to weird focus management.

The first step is to install the necessary packages:
apt-get install xbindkeys wmctrl zenity

With wmctrl we're able to switch to a window by specifying the name, while with xbindkeys we can bind Ctrl+Alt+M to open a zenity dialog then call wmctrl with the provided window name.

The only thing you need is the following file somewhere, let's call it keys.rc:
"WINDOWID='' app=$(zenity --text "App" --title "App" --entry) && wmctrl -R $app"
  control+alt + m

Now run xbindkeys -f keys.rc and we're done! Press Ctrl+Alt+M then type in the name of the window you want to switch to.

We can also add simpler bindings like this:
"wmctrl -R Firefox"
  control+alt + f

Now pressing Ctrl+Alt+F will switch to a firefox window.

Note that if it matches more window, only one of the window will be chosen obviously. The choice depends on xbindkeys.

I'm not using Alt+Tab anymore.

Sunday, March 24, 2013

Controlling audio volume in Awesome WM

I use awesome on my eeepc because it's much space and resource saving.
There are several possibilities for controlling volume in the Awesome window manager.
Today I'd like to share my way of doing it: using amixer for controlling the volume, and naughty for notifying the user.

Start by defining the following in your rc.lua (source discussion here):
volnotify = {}
volnotify.id = nil
function volnotify:notify (msg)
    self.id = naughty.notify({ text = msg, timeout = 1, replaces_id = self.id}).id
end

We use naughty for notifying the user instead of notify-send because of the "replaces_id" feature. It's used to replace an old notification with a new one. This is useful when you keep increasing the volume so that you only get one notification instead of stacking them up.
So the purpose of this code is to keep track of the id returned by naughty on each invocation, so that we can pass it to the next invocation.

function volume(incdec)
    awful.util.spawn_with_shell ("vol=$(amixer set Master 5%" .. incdec .. "|tail -1|cut -d % -f 1|cut -d '[' -f 2) && echo \\\"volnotify:notify('Volume $vol%')\\\"|awesome-client -", false)
end

function togglemute()
    awful.util.spawn_with_shell("vol=$(amixer set Master toggle|tail -n 1|cut -d '[' -f 3|cut -d ']' -f 1) && echo \\\"volnotify:notify('Volume $vol')\\\"|awesome-client -", false)
end

The first function is used to increase or decrease the volume. It accepts an argument of value either "+" or "-", then changes the master volume accordingly and finally displays a notification with the new volume.
The second function will toggle the mute state of the volume in a similar manner.

We are going to call these two functions whenever the user hits the media keys by binding new global keys as follows:

globalkeys = awful.util.table.join (globalkeys,
    awful.key({}, "XF86AudioMute", togglemute),
    awful.key({}, "XF86AudioLowerVolume", function() volume("-") end),
    awful.key({}, "XF86AudioRaiseVolume", function() volume("+") end)
)

Restart with Mod+Ctrl+R and that's it!