Hooks HOWTO
Not logged in

Instead of responding to different events in fixed ways, Minx allows end-users to customize its responses by defining their own hook functions. Thus, for example, when a new window is created, when a key is pressed, and so on, Minx will trigger the hooks for that particular event and act based on what the hooks return.

This page shows you how to use Minx's hooking functionality and makes various recommendations about do's and don'ts when writing your own hooks.

Introductory Examples

The basic pattern for defining hooks is to create the main window manager object and call the add() method of its hooks attribute before calling the wm object's start() method. The following subsections illustrate the procedure.

manage_hook

Minx triggers the manage_hook when a new window is created. It will pass to each manage_hook a minxlib.window object and expects a True or False return value to decide whether the new window should be managed by Minx or ignored.

Typically, in a manage_hook, you will examine the new window's properties and decide whether to return True (to have Minx manage the window) or False (to have the window ignored). For example, the following start-up script makes Minx ignore GKrellM but manage everything else:

   #!/usr/bin/env python

   import minx

   def my_manage_hook(w):
       prop = w.properties()
       if 'gkrellm' in prop['name'].lower():
          return False
       return True

   wm = minx.core.wm()
   wm.hooks.add('manage_hook', my_manage_hook)
   wm.start()

With that in place, you can position GKrellM at one of your screen corners and Minx will leave it alone.

Multiple Hook Functions

For something like the manage_hook, a single hook function is more than enough (you can check for all windows you want Minx to ignore using a regular expression). However, in general, you can define multiple functions for any hook as shown below:

   #!/usr/bin/env python

   import minx

   def ignore_foo(w):
       prop = w.properties()
       if prop['class'] == 'Xmessage' and prop['name'] == 'foo':
          return False
       return True

   def ignore_bar(w):
       prop = w.properties()
       if prop['class'] == 'Xmessage' and prop['name'] == 'bar':
          return False
       return True

   wm = minx.core.wm()
   wm.hooks.add('manage_hook', ignore_foo)
   wm.hooks.add('manage_hook', ignore_bar)
   wm.start()

Now, if you start a few xmessages with the following commands:

   xmessage -name foo 'Minx, please ignore me.' &
   xmessage -name bar 'Minx, please ignore me too.' &
   xmessage 'Minx, don't you dare ignore me!' &

The first two xmessage windows will be ignored while the third will be managed.

Of course, as mentioned above, you don't really need two manage_hook functions to achieve the above. But this example was only for illustration.

Short-circuiting a Hook Chain

In some situations, when you have multiple functions for a given hook, you may want to skip executing the remaining hooks after a particular hook is executed. You can do this by raising a short_circuit exception:

   #!/usr/bin/env python

   import minx
   from minx.core.hooks import short_circuit

   def ignore_foo(w):
       prop = w.properties()
       if prop['class'] == 'Xmessage' and prop['name'] == 'foo':
          raise short_circuit(False)
       return True

   def ignore_bar(w):
       prop = w.properties()
       if prop['class'] == 'Xmessage' and prop['name'] == 'bar':
          return False
       return True

   wm = minx.core.wm()
   wm.hooks.add('manage_hook', ignore_foo)
   wm.hooks.add('manage_hook', ignore_bar)
   wm.start()

Now, if ignore_foo() finds its condition is satisfied, there's no need to execute the remaining manage_hook functions. So, it raises a short_circuit exception and passes back a False through the exception to make Minx skip the remaining manage_hook functions and to make it ignore the xmessage named "foo".

If, however, the new window is not an xmessage named "foo", ignore_foo() will return True without raising an exception and Minx will continue to the next function in the manage_hook chain, viz., ignore_bar(). Since ignore_bar() is the last manage_hook in the above example, there's no point in it raising an exception (because there are no more hooks left in the chain to short-circuit).

Again, the above example is contrived because you will usually not need more than one manage_hook.

Hook Do's and Don'ts

Here are some things to keep in mind when writing hook functions:

NOTE: The only exception to raising exceptions from inside hooks is when you want to short-circuit the remaining hooks in a chain with a minx.core.hooks.short_circuit exception. But even this, you should only do when absolutely necessary (in general, it's bad form to short-circuit because various modules may depend on their hooks being executed).