This page describes the Plan 9 port of Object Icon. This port does not use Plan 9’s Posix porting library (“APE”), but rather attempts to be a pure Plan 9 port, using Plan 9’s native features directly.

A full graphics implementation is included; however it requires a modified version of the rio window manager in order to work. This is called riox and is compiled along with the rest of Object Icon. It is described in full on this page.

Source code

The source code is contained on a separate branch, and can be obtained with the following command :-

svn co svn:// objecticon

This directory must then be made available from within plan 9, either by copying it or sharing it via 9p (eg using the u9fs program).


Firstly, ensure that the sh program is available on your path. It can be found in /bin/ape, and is needed to run the test scripts. If it is not on your path, edit your profile to include the command :-

bind -a /bin/ape /bin

Then, from the checked out Object Icon directory, run the command :-


This sets up the mkfiles and other configuration files. Now run

mk all test

to compile and test everything. Hopefully at the end “Testing successful” will appear.

Path setup

To add the Object Icon executables to your path, and set up the usual environment variables, it is necessary to “source” the paths.rc file from your profile file. For example, I have the following line in my profile :-

. /usr/rparlett/objecticon/paths.rc


As mentioned in the introduction, the modified window manager riox must be used with the graphics facilities.


One notable limitation relates to keyboard handling. riox reads keyboard input from the cons device, which simply produces a stream of UTF-8 characters. This means there is no way to tell when the user presses one of the modifier keys (shift, control, etc.), since these do not by themselves produce characters. In turn, this means that operations which rely on a modifier key being pressed together with a key or mouse button will not work correctly. Examples include shift and mouse or cursor key in a text area or list (to move the cursor whilst keeping the selection), and control and mouse in a list (to multi-select rows). Keyboard release events are also never generated, regardless of a Window’s input mask setting.

Using the current window

The environment variable OI_USE_WIN allows the first window opened to take over the current window, assumed to be mounted in the directory given by the environment variable wdir (default /dev) . If OI_USE_WIN is unset, or is 0, then the current window is not used. Otherwise, it is taken over, and adjusted depending on the value :-

It is important that the program running does not produce output to the console, as this will overwrite the graphics drawn to the window.

Mounted window directories

Windows are mounted under the directory given by the environment variable OI_WIN_MNTGEN (default /n). A typical example of a mounted window directory might be /n/oix-win.543.1. Using mounted window directories presents a problem, however, which can be illustrated by running the following commands :-

% mount $wsys /n/win new
% page -w something.pdf    # View any pdf (keep this window open).
% unmount /n/win

You would expect the last command to close the window opened by the first. But in fact it doesn't appear to do anything. The reason for this is that the page command has, under the covers, copied the namespace used by the shell, by calling the system function rfork with the RFNAMEG flag. This means there are two references to the window mount, and the unmount command only removes one of them. The window thus stays open until the page window is closed.

There are several ways to deal with this problem, and to choose between them an environment variable OI_WIN_NAMEG is provided. If the variable is unset, or is 0, then oix will look under the directory indicated by the environment variable OI_WIN_WSYS (default /dev/wsys) for a directory corresponding to the window mount directory, and, if found, use it instead, after unmounting the window mount. Since there is no longer a mounted directory, the problem of “mount capture” doesn't arise. The only drawback with this technique is that it relies on another window directory already being mounted and providing the alternative wsys directory.

If OI_WIN_NAMEG is 1 then the switch just described isn't made, and the mounted directory is always used. This isn't really a solution at all of course, but the option is there for completeness’ sake.

If OI_WIN_NAMEG is 2, then oix will use rfork(RFNAMEG) to copy the namespace, and then mount windows as usual. Because these mounts will be in a copied “private” namespace, these mounts cannot be captured by other programs. This option does however, have two disadvantages. Firstly, the program won't be able to manipulate the original namespace, and secondly the rfork will potentially capture other mounts (it is odd that this solution can actually cause more of the original problem).

Additional methods

The graphics.Window class contains an extra method, get_dir(), which returns the path of the directory on which the window is mounted. From this directory, all of the usual riox window files may be accessed, giving complete flexibility to the client program.


File systems

The Plan 9 implementation includes some classes for providing file system servers using Plan 9’s 9P protocol. Full details can be found on this page.


The I/O package exhibits some necessary differences in the Plan 9 implementation; these are detailed on this page.