Hooks are a central feature of Minx and are used internally to be able to respond to various events generated by the X server. Minx also allows end-users to define their own hooks and triggers those hooks in response to different events/situations.
This page documents all of Minx's currently supported hooks, both internal ones and those meant for end-users. Here is the complete list:
Minx triggers these hooks to allow end-users to customize how the window manager responds to different events.
When you start Minx (by calling the wm object's start method), it goes through the following sequence of steps:
- Connect to the X server
- Configure X event masks and key bindings
- Trigger the init hook
- Manage existing windows
- Initiate the X event loop
The intent of the init hook is to allow you to insert some custom initialization before Minx starts managing windows and processing events but after it has obtained a valid X connection. When the init hook is called, you can be sure that the wm object's display and root_windows attributes are available to you. The display attribute is an instance of the minxlib::display class and isn't something you would usually need to deal with directly. However, wm.root_windows is almost certainly an attribute of interest: it contains a list of minxlib::root_window objects, one for each physical screen you have.
Typically, in the init hook, you will create layouts for each screen as shown below:
#!/usr/bin/env python import minx def my_init_hook(m): scr = m.root_windows m.layouts.add(minx.layout.tall(m, scr)) if len(scr) > 1: for w in scr[1:]: m.layouts.add(minx.layout.full(m, w)) wm = minx.core.wm() wm.hooks.add('init_hook', my_init_hook) wm.start()
The above example sets up the first screen to use the tall layout and the full layout on the remaining screens. Note that the tall layout has not yet been implemented; it is used above merely for illustration.
There is no per-screen restriction on the number of layouts nor any requirement that a layout occupy the entire screen. We kept it simple for the sake of the example. However, you can create multiple layouts per screen, assign them to different parts of the screens, and use whatever criteria that fit your needs and that you can code up.
Minx triggers this 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.
Although you can define multiple functions for any hook, you should not define more than are actually necessary. For the manage_hook, you almost never need more than one in place. A single manage_hook is enough to determine whether a given window should be managed or ignored. For example, the following manage_hook ignores GKrellM as well as xmessages named "foo" and "bar":
#!/usr/bin/env python import minx def my_manage_hook(w): prop = w.properties() if 'gkrellm' in prop['name'].lower(): return False c = prop['class'] n = prop['name' ] if c == 'Xmessage' and (n == 'foo' or n == 'bar'): return False return True wm = minx.core.wm() wm.hooks.add('manage_hook', my_manage_hook) wm.start()
In a similar vein, you can use regular expressions and other such techniques to check against a multitude of patterns to decide whether or not to manage a given window without needing more than one manage_hook.
Once a window gets past the manage hook, to manage it, Minx will assign it to a layout. The receptive layout hook, allows you to find or create a layout for each new window. Here is an example:
#!/usr/bin/env python import minx def my_receptive_layout_hook(w): prop = w.properties() if 'gimp' in prop['class'].lower(): global wm try: L = wm.layouts.find('gimp') return L except minx.core.layman.unknown_layout: parent = wm.root_windows[w.screen()] return minx.layout.gimp(wm, parent) return None wm = minx.core.wm() wm.hooks.add('receptive_layout_hook', my_receptive_layout_hook) wm.start()
The above example returns a new gimp layout for the first Gimp window and reuses that layout for subsequent windows that Gimp creates. For all other window types, it returns nothing, which makes Minx use its default policies for layout selection (read all about that on the layout manager's API page).
Please note that there is no gimp layout. Thus, the above code won't actually work; it is only meant to illustrate how the receptive layout hook is meant to be used.
Default Key Bindings
Key bindings are simply hooks whose names follow the pattern described here. Whenever a keyboard event matching a key binding is generated, Minx will translate it into the name of the key binding and then trigger the hooks corresponding to that name.
This section documents the default key bindings that Minx sets up. Of course, you can change these key bindings or even remove them as described in the Key Bindings HOWTO.
Bowing to convention, Minx uses ALT + Tab to move input focus to the next top-level window in its list of windows.
ALT + SHIFT + Tab is setup to move input focus to the previous window in the list of top-level windows currently being managed.
NOTE: The order in which you specify modifiers is not significant. Thus, the above key binding could just as well have been A-S-Tab instead of S-A-Tab. The only reason we chose S-A-Tab is because, with appropriate spacing, the code for this and A-Tab lines up nicely. No deep mystery here.
ALT + F4 kills the currently focused window. If the window supports the WM_DELETE_WINDOW protocol, Minx will use that to kill the window; otherwise, it will nuke the window using a brute force kill.
CTRL + F4 kills the currently focused window using brute force. This key binding is meant for those applications that advertise support for the WM_DELETE_WINDOW protocol but fail to implement it properly, i.e., ignore the WM_DELETE_WINDOW request without good cause. With this key binding, Minx will use brute force to kill the window, without bothering with niceties such as WM_DELETE_WINDOW.
CTRL + ALT + T will launch a terminal window. By default, Minx uses xterm, but you can change that as shown below:
#!/usr/bin/env python import minx conf = minx.core.config() conf.terminal = 'gnome-terminal' wm = minx.core.wm(conf) wm.start()
This key binding makes Minx get out of its event loop. Usually, this will also quit the window manager (unless you have code in your Minx init file after the call to wm.start()).
Minx defines and uses these hooks internally to respond to events generated by the X server. In general, you should not override these hooks unless you really, really need to and know what you're doing.
minx.core.xevents uses this hook to handle creation of new windows. The hook is passed a create_notify event. Minx responds to this event by checking if the new window should be managed or not and, if so, it adds the window to its internal data structures.
Minx triggers the manage_hook as part of the checks to determine whether or not to manage the new window.
The minx.core.window module uses this hook to clear its internal data structures when a top-level window is destroyed.
minx.core.xevents uses this hook to honor X configure requests.
Both minx.core.xevents and minx.core.window define x_map_request hooks. The minx.core.window hook handles X map requests for top-level windows while the one in the xevents module handles the map requests for non-top-level windows.
minx.core.xevents defines an x_map_notify hook to add newly mapped windows to the window manager's focus_list.
minx.core.xevents defines an x_unmap_notify hook to remove an unmapped window from the window manager's focus list and to focus the next window in the list.
The minx.core.window module defines an x_configure_notify hook to be able to update some internal state for a top-level window after it has been configured.
minx.core.xevents responds to key presses using this hook.