Configuring and extending Notion with Lua
Copyright © 2010-2011 The Notion Team.
Copyright © 2003-2009 Tuomo Valkonen.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''.
The latest version of this document can be found at http://notion.sourceforge.net in HTML and PDF formats. Updates are welcome, preferably in the form of patches against the LATEX sources which can be found in the git repository at git://notion.git.sourceforge.net/gitroot/notion/notion-doc (http://notion.git.sourceforge.net/git/gitweb.cgi?p=notion/notion-doc;a=summary)
This document is an ``advanced user'' manual for the X11 window manager Notion. It is an attempt at documenting things that go into Notion's configuration files, how to configure Notion by simple modifications to these files and how to write more complex extensions in Lua, the lightweight configuration and scripting language used by Notion.
Readers unfamiliar with Lua might first want to first glance at some Lua documentation at
although this should not be strictly necessary for basic modifications of configuration files for anyone with at least some familiarity with programming languages.
Back in this document, first in chapter 2 some key concepts and relations are explained. These include the module system, and Notion's object (or ``region'') and class hierarchies. While it may not be necessary to study the latter for basic copy-paste modifications of configuration files - for that you should not really need this manual either - it is, however, essential to for more extensive customisation, due to the semi-object-oriented nature of most of Notion's scripting interface. Knowing the different object types also helps dealing with the different binding ``contexts'' (see Section 3.3) that to some extent mirror these classes.
The new user, fed up with the default key bindings and eager to just quickly configure Notion to his liking, may therefore just want to skip to Chapter 3, and attempt to work from therefore. That chapter provides the very basic Notion configuration know-how is provided: all the different configuration files and their locations are explained, instructions are given to allow the reader to configure bindings and so-called ``winprops'', and the statusbar templates are also explained.
Next, Chapter 4 explains the notion of drawing engines and graphical styles and how to write new looks for Notion. More advanced aspects of Notion's scripting interface are documented in Chapter 5. Finally, most of the functions provided by Notion's scripting interface are listed and documented in the Function reference in Chapter 6. At the end of the document an alphabetical listing of all these functions may be found.
The purpose of this chapter to explain some of key concepts and relations you need to understand before reading the following chapters. These include modules explained in section 2.1 and the Notion class and object hierarchies, section 2.2.
Notion has been designed so that the 'notion' executable only implements some basic services on top of which very different kinds of window managers could be build by loading the appropriate 'modules'. On modern system these modules are simply dynamically loaded .so libraries. On more primitive systems, or if you want to squeeze total size of the executable and libraries, the modules can optionally be statically linked to the main binary, but must nevertheless be loaded with the dopath function. Modules may also include Lua code.
Currently Ion provides the following modules:
So-called drawing engines are also implemented as a modules, but they are not discussed here; see chapter 4.
The stock configuration for the notion executable loads all of the modules mentioned above except mod_dock. The stock configuration for the pwm3 executable (which differs from the notion executable in a few configuration details) loads another set of modules.
While Notion does not have a truly object-oriented design2.1, things that appear on the computer screen are, however, quite naturally expressed as such ``objects''. Therefore Notion implements a rather primitive OO system for these screen objects and some other things.
It is essential for the module writer to learn this object system, but also people who write their own binding configuration files necessarily come into contact with the class and object hierarchies - you need to know which binding setup routines apply where, and what functions can be used as handlers in which bindings. It is the purpose of this section to attempt to explain these hierarchies. If you do not wish the read the full section, at least read the summary at the end of it, so that you understand the very basic relations.
For simplicity we consider only the essential-for-basic-configuration Notioncore, mod_tiling and mod_query classes. See Appendix B for the full class hierarchy visible to Lua side.
One of the most important principles of object-oriented design methodology is inheritance; roughly how classes (objects are instances of classes) extend on others' features. Inheritance gives rise to class hierarchy. In the case of single-inheritance this hierarchy can be expressed as a tree where the class at the root is inherited by all others below it and so on. The tree below lists out the Notion class hierarchy and below we explain what features of Notion the classes implement.
Obj |-->WRegion | |-->WClientWin | |-->WWindow | | |-->WRootWin | | |-->WMPlex | | | |-->WFrame | | | `-->WScreen | | `-->WInput (mod_query) | | |-->WEdln (mod_query) | | `-->WMessage (mod_query) | |-->WGroup | | |-->WGroupWS | | `-->WGroupCW | `-->WTiling (mod_tiling) `-->WSplit (mod_tiling)
Classes implemented by the mod_tiling module:
Classes implemented by the mod_query module:
There are also some other ``proxy'' classes that do not refer to objects on the screen. The only important one of these for basic configuration is WMoveresMode that is used for binding callbacks in the move and resize mode.
Even though it often indicates a design mistake, sometimes it can be useful to have run-time access to the types of objects.
For example, to check wether a given object is of type WMPlex, the following C code can be used:
if(obj_is((Obj*)cwin, &CLASSDESCR(WMPlex))) ....
Its lua counterpart is:
if(obj_is(cwin, "WMPlex")) ....
While there's also an 'obj_cast' method available, C structs can be freely cast to their 'superclass' using a regular C cast, for example:
bool input_fitrep(WInput *input, WWindow *par, const WFitParams *fp) { if(par!=NULL && !region_same_rootwin((WRegion*)input, (WRegion*)par)) return FALSE; ...
WRootWins |-->WGroupWSs |-->WTilings |-->WClientWins in full screen mode `-->WFrames |-->WGroupCWs |-->WClientWins |-->WFrames for transients `-->a possible WEdln or WMessage
WRegions have very little control over their children as a parent.
The manager WRegion has much more control over its
managed WRegions. Managers, for example, handle resize requests,
focusing and displaying of the managed regions. Indeed the manager--managed
relationship gives a better picture of the logical ordering of objects on
the screen. Again, there are generally few limits, but the most common
hierarchy is given in Figure . Note that sometimes
the parent and manager are the same object and not all regions may have
a manager, but all non-screen regions have a parent--a screen if not
anything else.
WRootWins |-->WGroupCWs for full screen WClientWins | |-->WClientWins | `-->WFrames for transients (dialogs) | `--> WClientWin |-->WGroupWSs for workspaces | |-->WTiling | | |-->WFrames | | | `-->WGroupCWs (with contents as above) | | `-->possibly a WStatusBar or WDock | |-->WFrames for floating content | |-->possibly a WEdln, WMessage or WMenu | `-->possibly a WStatusBar or WDock (if no tiling) `-->WFrames for sticky stuff, such as the scratchpad
Note that a workspace can manage another workspace. This can be achieved with the WGroup.attach_new function, and allows you to nest workspaces as deep as you want.
In the presense of Xinerama there may be WScreen objects at the top of the manager-managed tree instead of WRootWin.
In the standard setup, keeping queries, messages and menus out of consideration:
This chapter should help your configure Notion to your liking. As you probably already know, Notion uses Lua as a configuration and extension language. If you're new to it, you might first want to read some Lua documentation as already suggested and pointed to in the Introduction before continuing with this chapter.
Section 3.1 is an overview of the multiple configuration files Notion uses and as a perhaps more understandable introduction to the general layout of the configuration files, a walk-through of the main configuration file cfg_notion.lua is provided in section 3.2. How keys and mouse action are bound to functions is described in detail in 3.3 and in section 3.5 winprops are explained. Finally, the statusbar is explained in 3.6.2. For a reference on exported functions, see section 6.
Notion stores its stock configuration files in /usr/local/etc/notion/ unless you, the OS package maintainer or whoever installed the package on the system has modified the variables PREFIX or ETCDIR in system.mk before compiling Notion. In the first case you probably know where to find the files and in the other case the system administrator or the OS package maintainer should have provided documentation to point to the correct location. If these instructions are no help in locating the correct directory, the command locate cfg_notion.lua might help provided updatedb has been run recently.
User configuration files go in ~/.notion/. Notion always searches the user configuration file directory before the stock configuration file directory for files. Therefore, if you want to change some setting, it is advised against that you modify the stock configuration files in-place as subsequent installs of Notion will restore the stock configuration files. Instead you should always make a copy of the stock file in ~/.notion/ and modify this file. For sake of maintainability of your customised configuration, it is recommended against copying all of the files there. Only copy those files you actually need to modify. Most simple customisations, such as changes in a few bindings, are best done entirely within cfg_notion.lua.
All the configuration files are named cfg_*.lua with the ``*'' part varying. The configuration file for each module mod_modname is cfg_modname.lua, with modname varying by the module in question. Configuration files can also be compiled into .lc files, and these are attempted by the configuration file search routines before .lua files.
The following table summarises these and other configuration files:
File |
cfg_notion.lua |
cfg_notioncore.lua |
cfg_kludges.lua |
cfg_layouts.lua |
cfg_tiling.lua cfg_query.lua cfg_menu.lua cfg_dock.lua cfg_statusbar.lua ... |
Additionally, there's the file look.lua that configures the drawing engine, but it is covered in chapter 4.
As already mentioned cfg_notion.lua is Notion's main configuration
file. Some basic 'feel' settings are usually configured there and
the necessary modules and other configuration files configuring some
more specific aspects of Notion are loaded there. In this section we
take a walk through the stock cfg_notion.lua.
Notice that most of the settings are commented-out (--
is a
line comment in Lua) in the actual file, as they're the defaults
nevertheless.
The first thing done in the file, is to set
META="Mod1+" ALTMETA=""These settings cause most of Notion's key bindings to use Mod1 as the modifier key. If ALTMETA is set, it is used as modifier for the keys that don't normally use a modifier. Note that these two are Lua variables used in the configuration files only, and not Notion settings. For details on modifiers and key binding setup in general, see section 3.3.
Next we do some basic feel configuration:
ioncore.set{ dblclick_delay=250, kbresize_delay=1500, }
These two will set the delay between button presses in a double click, and the timeout to quit resize mode in milliseconds.
ioncore.set{ opaque_resize=true, warp=true }
The first of these two settings enables opaque resize mode: in move/resize move frames and other objects mirror you actions immediately. If opaque resize is disabled, a XOR rubber band is shown during the mode instead. This will, unfortunately, cause Notion to also grab the X server and has some side effects.
There are some other options as well; see the documentation for ioncore.set for details.
As a next step, in the actual cfg_notion.lua file, we load cfg_defaults.lua. However, it is merely a convenience file for doing exactly what we will going through below, and what is commented out in the actual file. If you do not want to load what cfg_defaults.lua loads, just comment out the corresponding line, and uncomment the lines for the files that you want:
--dopath("cfg_defaults") dopath("cfg_notioncore") dopath("cfg_kludges") dopath("cfg_layouts")
Most bindings and menus are defined in cfg_ioncore.lua. Details on making such definitions follow in sections 3.3 and 3.4, respectively. some kludges or ``winprops'' to make some applications behave better under Notion are collected in cfg_kludges.lua; see section 3.5 for details. In addition to these, this file lists quite a few statements of the form
ioncore.defshortening("[^:]+: (.*)(<[0-9]+>)", "$1$2$|$1$<...$2")These are used to configure how Notion attempts to shorten window titles when they do not fit in a Tab. The first argument is a POSIX regular expression that is used to match against the title and the next is a rule to construct a new title of a match occurs. This particular rule is used to shorten e.g. 'Foo: barbaz<3>' to 'barba...<3>'; for details see the function reference entry for ioncore.defshortening. Finally, cfg_layouts.lua defines some workspace layouts, available through the F9 workspace creation query.
To actually be able to do something besides display windows in full screen mode, we must next load some modules:
dopath("mod_query") dopath("mod_menu") dopath("mod_tiling") dopath("mod_statusbar") --dopath("mod_dock") dopath("mod_sp")
In the stock configuration file setup, most key and mouse bindings are set from the file cfg_notioncore.lua while module-specific bindings are set from the modules' main configuration files (cfg_modname.lua). This, however, does not have to be so as long as the module has been loaded prior to defining any module-specific bindings.
Bindings are defined by calling the function defbindings with the ``context'' of the bindings and the a table of new bindings to make. The context is simply string indicating one of the classes of regions (or modes such as WMoveresMode) introduced in section 2.2, and fully listed in appendix B, although not all define a binding map. For example, the following skeleton would be used to define new bindings for all frames:
defbindings("WFrame", { -- List of bindings to make goes here. })
There has been some confusion among users about the need to define the
``context'' for each binding, so let me try to explain this design
decision here. The thing is that if there was a just a simple 'bind this
key to this action' method without knowledge of the context, some
limitations would have to be made on the available actions and writing
custom handlers would be more complicated. In addition one may want to
bind the same function to different key for different types of objects.
Indeed, the workspace and frame tab switching functions are the same both
classes being based on WMPlex, and in the stock configuration the
switch to n
Currently known contexts include:
`WScreen',
`WMPlex',
`WMPlex.toplevel',
`WFrame',
`WFrame.toplevel',
`WFrame.floating',
`WFrame.tiled',
`WFrame.transient',
`WMoveresMode',
`WGroup',
`WGroupCW',
`WGroupWS',
`WClientWin',
`WTiling', and
`WStatusBar'.
Most of these should be self-explanatory, corresponding to objects
of class with the same name. The ones with `.toplevel' suffix
refer to screens and ``toplevel'' frames, i.e. frames that are
not used for transient windows. Likewise `.transient' refers
to frames in transient mode, and `.tiled' and `.floating'
to frames in, respectively, tiled and floating modes.
The following subsections describe how to construct elements of the
binding table. Note that defbindings adds
the the newly defined bindings to the previous bindings of the context,
overriding duplicates. To unbind an event, set the handler parameter
to nil for each of the functions to be described in the following
subsections.
Also note that when multiple objects want to handle a binding, the
innermost (when the root window is considered the outermost) active object
in the parent-child hierarchy (see Figure
Unlike in Ion2, in Notion binding handlers are not normally passed as
``anonymous functions'', although this is still possible. The preferred
method now is to pass the code of the handler as a string. Two following
special variables are available in this code.
For example, supposing _ (underscore) is a WFrame, the
following handler should move the active window to the right, if
possible:
To suppress error messages, each binding handler may also be accompanied
by a ``guard'' expression that blocks the handler from being called when
the guard condition is not met. Currently the following guard expressions
are supported (for both _sub and _chld):
The descriptions of the individual bindings in the binding table argument
to defbindings should be constructed with the following
functions.
Key presses:
The actions that most of these functions correspond to should be clear
and as explained in the reference, kpress_wait is simply
kpress with a flag set instructing Notioncore wait for
all modifiers to be released before processing any further actions.
This is to stop one from accidentally calling e.g.
WRegion.rqclose multiple times in a row. The
submap function is used to define submaps or
``prefix maps''. The second argument to this function is table listing
the key press actions (kpress) in the submap.
The submap_enter handler is called when the submap
is entered, in which this handler is defined. Likewise, the
submap_wait handler is called when all modifiers
have been released while waiting for further key presses in the submap.
The parameters keyspec and buttonspec are explained below
in detail. The parameter handler is the handler for the binding,
and the optional parameter guard its guard. These should normally
be strings as explained above.
For example, to just bind the key Mod1+1 to switch to the first
workspace and Mod1+Right to the next workspace, you would make the
following call
Note that _:switch_nth(1) is the same as calling
WMPlex.switch_next(_, 1) as WScreen inherits
WMPlex and this is where the function is actually defined.
Similarly to the above example, to bind the key sequence Mod1+k n
switch to the next managed object within a frame, and Mod1+k 1 to the
first, you would issue the following call:
As seen above, the functions that create key binding specifications require
a keyspec argument. This argument should be a string containing the
name of a key as listed in the X header file keysymdef.h3.1 without the XK_ prefix.
Most of the key names are quite intuitive while some are not. For example,
the Enter key on the main part of the keyboard has the less common
name Return while the one the numpad is called KP_Enter.
The keyspec string may optionally have multiple ``modifier'' names
followed by a plus sign (+) as a prefix. X defines the following
modifiers:
Shift, Control, Mod1 to Mod5,
AnyModifier and Lock.
X allows binding all of these modifiers to almost any key and while this
list of modifiers does not explicitly list keys such as
Alt that are common on modern keyboards, such
keys are bound to one of the ModN. On systems running XFree86
Alt is usually Mod1. On Suns Mod1 is the diamond key
and Alt something else. One of the ``flying window'' keys on so
called Windows-keyboards is probably mapped to Mod3 if you have
such a key. Use the program xmodmap
to find out what exactly is bound where.
Notion defaults to AnyModifier in submaps. This can sometimes lead to
unwanted effects when the same key is used with and without explicitly
specified modifiers in nested regions. For this reason, Notion recognises
NoModifier as a special modifier that can be used to reset this
default.
Notion ignores the Lock modifier and any ModN (
N = 1...5
Button specifications are similar to key definitions but now
instead of specifying modifiers and a key, you specify modifiers
and one of the button names Button1 to
Button5. Additionally the
specification may end with an optional area name following an @-sign.
Only frames currently support areas, and the supported values in this
case are
`border', `tab', `empty_tab', `client'
and nil (for the whole frame).
For example, the following code binds dragging a tab with the first
button pressed to initiate tab drag&drop handling:
The default binding configuration contains references to the variables
META and ALTMETA instead of directly using the default
values of `Mod1+' and `' (nothing). As explained in
section 3.2, the definitions of these variables
appear in cfg_notion.lua. This way you can easily change the the
modifiers used by all bindings in the default configuration without
changing the whole binding configuration. Quite a few people prefer
to use the Windows keys as modifiers because many applications already
use Alt. Nevertheless, Mod1 is the default as a key bound
to it is available virtually everywhere.
In the stock configuration file setup, menus are defined in the file
cfg_menus.lua as previously mentioned. The mod_menu module
must be loaded for one to be able to define menus, and this is done with
the function defmenu provided by it.
Here's an example of the definition of a rather simple menu with a submenu:
The menuentry function is used to create an entry in the
menu with a title and an entry handler to be called when the menu entry
is activated. The parameters to the handler are similar to those of binding
handlers, and usually the same as those of the binding that opened the menu.
The submenu function is used to insert a submenu at that
point in the menu. (One could as well just pass a table with the menu
entries, but it is not encouraged.)
The menu module predefines the following special menus. These can be used
just like the menus defined as above.
The ``ctxmenu'' is a special menu that is assembled from a defined context
menu for the object for which the menu was opened for, but also includes
the context menus for the manager objects as submenus.
Context menus for a given region class are defined with the
defctxmenu function. This is other ways similar to
defmenu, but the first argument instead being the name
of the menu, the name of the region class to define context menu for.
For example, here's part of the stock WFrame context menu
definition:
Some of the same ``modes'' as were available for some bindings
may also be used: `WFrame.tiled', `WFrame.floating',
and `WFrame.transient'.
The following functions may be used to display menus from binding
handlers (and elsewhere):
Each of these functions takes three arguments, which when
called from a binding handler, should be the parameters to the handler, and
the name of the menu. For example, the following snippet of of code binds
the both ways to open a context menu for a frame:
The so-called ``winprops'' can be used to change how
specific windows are handled and to set up some kludges to deal with
badly behaving applications. They are defined by calling the function
defwinprop with a table containing the properties to set and the
necessary information to identify a window. The currently supported
winprops are listed below, and the subsequent subsections explain the
usual method of identifying windows, and how to obtain this information.
These properties can be used to tell Notion how to treat the matched windows:
Additionally, the winprops
max_size,
min_size,
aspect,
resizeinc,
and
ignore_max_size,
ignore_min_size,
ignore_aspect,
ignore_resizeinc,
may be used to override application-supplied size hints. The four
first ones are tables with the fields w and h, indicating
the width and height size hints in pixels, and the latter ignore
winprop is a boolean.
Finally, the boolean
userpos option may be used to
override the USPosition flag of the size hints. Normally,
when this flag is set, Notion tries to respect the supplied window
position more than when it is not set. Obviously, this makes sense
only for floating windows.
The primary identification information supported is the
class,
role and
instance of the window.
Secondary filters are the
name,
is_transient and
is_dockapp fields, or a
custom matching algorithm.
Notion first filters the winprops based on the primary identification fields.
Of those winprops that match the primary identification fields, the most
recently defined winprop that also matches the secondary filters is used.
The primary identification fields are strings, and must exactly match the
corresponding information obtained from the window's properties.
Notion looks for a winprop in the order listed by the following
table. An 'E' indicates that the field must be set in the winprop
and it must match the window's corresponding property exactly. An asterisk '*'
indicates that a winprop where the field is not specified (or is itself an
asterisk in case of the first three fields) is tried.
The name field is a Lua-style regular expression matched against
the window's title. The is_transient field is a boolean that can
be used to include or exclude transients only, while the is_dockapp
field is set by Notion for the dock windows of Window Maker dockapp protocol
dockapps. Usually this is the only information available for these
icon windows.
If a custom matching algorithm is used, the secondary filters are ignored.
A custom matching algorithm can be specified by simple adding a lua function
named match to the winprop table. This function will be passed 3
parameters: the winprop itself, the client window against which the winprop
must be matched, and the identification information of this client window.
The identification information of the client window is a table containing the
class,
role,
instance,
is_transient and
is_dockapp fields of the
window.
The 'Window info' context menu entry (Mod1+M or Button3 on a tab)
can be used to list the identification information required to set winprops
for a window and all the transient windows managed within it.
Another way to get the identification information is to use xprop.
Simply run To get class and instance, simply run xprop WM_CLASS
and click on the particular window of interest. The class is the latter of
the strings while the instance is the former. To get the role - few
windows have this property - use the command xprop WM_ROLE.
This method, however, will not work on transients.
So-called ``transient windows'' are usually short-lived dialogs (although
some programs abuse this property) that have a parent window that they are
``transient for''. On tiled workspaces Notion displays these windows
simultaneously with the parent window at the bottom of the same frame.
Unfortunately xprop is stupid and can't cope with this situation,
returning the parent window's properties when the transient is clicked on.
For this reason you'll have to do a little extra work to get the properties
for that window.3.3
Finally, it should be mentioned that too many authors these days
``forget'' to set this vital identification to anything meaningful:
everything except name is the same for all of the program's
windows, for example. Some other programs only set this information
after the window has been mapped, i.e. the window manager has been
told to start managing it, which is obviously too late.
Gtk applications in particular are often guilty on both counts.
The following is absolutely necessary for Acrobat reader:
The following winprop should place xterm started with command-line parameter
-name sysmon and running a system monitoring program in a
particular frame:
For this example to work, we have to somehow create a frame named
`sysmonframe'. One way to do this is to make the following
call in the Mod1+F3 Lua code query:
Recall that _ points to the multiplexer (frame or screen) in which
the query was opened. Running this code should open a new query prefilled
with the current name of the frame. In our example we would change the
name to `sysmonframe', but we could just as well have used the
default name formed from the frame's class name and an instance number.
Most window managers have some kind of 'dock' or statusbar/panel to give a
quick overview of running processes and system status. Notion is no
different - actually we have several options.
When a part of the screen is reserved for this purpose, in Notion this is
called a ``status display'' or ``stdisp''. You can have one stdisp per Screen
- it is independent of the current workspace or tiling.
Notion has 2 kinds of stdisp's: if you want to use one or more existing
panel/dock applications, you can use mod_dock with the ``embedded''
mode. Alternatively, you can use the built-in mod_statusbar. Since a
Screen can only hold one stdisp, you can have either - not both.
Generally, if you want to use some panel application like the xfce4-panel,
fbpanel or the gnome-panel, use an embedded dock. When used in this way, it is
common to add only one panel to the dock and have it span the entire width of
the screen. However, the dock does support adding multiple applications to it,
so if you prefer WindowMaker-style dockapps, mod_dock (either embedded
or floating) is also the way to go.
Given the high quality of 3rd-party panels, mod_statusbar is mostly
a legacy part of Notion.
The mod_statusbar module provides a statusbar that adapts to
layouts of tilings, using only the minimal space needed.
The statusbar is configured in cfg_statusbar.lua. Typically,
the configuration consists of two steps: creating a statusbar with
mod_statusbar.create, and then launching the separate
ion-statusd status daemon process with
mod_statusbar.launch_statusd. This latter phase is done
automatically, if it was not done by the configuration file, but
the configuration file may pass extra parameters to ion-statusd
monitors. (See Section 5.5 for more information on
writing ion-statusd monitors.)
A typical cfg_statusbar.lua configuration might look as follows:
The template specifies what is shown on the statusbar; for information
on the other options to mod_statusbar.create, see the reference.
Strings of the form `%spec' tokens specially interpreter by
the statusbar; the rest appears verbatim. The spec typically
consists of the name of the value/meter to display (beginning with a latin
alphabet), but may be preceded by an alignment specifier and a number
specifying the minimum width. The alignment specifiers are: `>'
for right, `<' for left, and `|' for centring. Additionally,
space following `%' (that is, the string `% '), adds
``stretchable space'' at that point. The special string `%filler'
may be used to flush the rest of the template to the right end of
the statusbar.
The stretchable space works as follows: mod_statusbar remembers
the widest string (in terms of graphical presentation) that it has
seen for each meter, unless the width has been otherwise constrained.
If there is stretchable space in the template, it tries to make the
meter always take this much space, by stretching any space found in
the direction indicated by the alignment specifier: the opposite
direction for left or right alignment, and both for centring.
The special `%systray' and `%systray_*'
(`*' varying) monitors indicate where to place system tray
windows. There may be multiple of these. KDE-protocol system tray
icons are placed in `%systray' automatically, unless disabled
with the systray option. Otherwise the statusbar winprop may
be used to place any window in any particular `%systray_*'.
The part before the first
underscore of each monitor name, describes the script/plugin/module
that provides the meter, and any configuration should be passed
in the a corresponding sub-table mod_statusbar.launch_statusd.
Notion comes with date, load and mail (for plain old mbox)
ion-statusd monitor scripts. More may be obtained from
the scripts repository [1]. These included scripts
provide the following monitors and their options
Options: date_format: The date format in as seen above,
in the usual strftime format. formats: table of
formats for additional date monitors, the key being the name
of the monitor (without the `date_' prefix).
Monitors: `date' and other user-specified ones with the
`date_' prefix.
Options: update_interval: Update interval in milliseconds
(default 10s). important_threshold: Threshold above which
the load is marked as important (default 1.5), so that the
drawing engine may be suitably hinted. critical_threshold:
Threshold above which the load is marked as critical (default 4.0).
Monitors: `load' (for all three values),
`load_1min', `load_5min' and `load_15min'.
Options: update_interval: Update interval in milliseconds
(default 1min). mbox: mbox-format mailbox location
(default
Monitors: `mail_new', `mail_unread',
`mail_total', and corresponding
`mail_*_new', `mail_*_unread', and `mail_*_total'
for the additional mailboxes (`*' varying).
This chapter first gives in section 4.1 a general outline
of how drawing engines are used, of style specifications and then
in section 4.2 describes how to specify styles
for the default drawing engine. Some additional settings and
user attributes are explained in Sections 4.3.
Notion's drawing routines are abstracted into so-called drawing engine
modules that can, again depending on the system, be dynamically
loaded as needed. The drawing engine modules provide ``brushes''
that objects can use to draw some high-level primitives such
as borders and text boxes (in addition to simple text and rectangle
drawing) on their windows and configure e.g. the shape and
background of the window. While the drawing engines therefore
do not directly implement looks for each possible object (that
would hardly be maintainable), different brush styles can be
used to give a distinctive look to different objects and engines
could interpret some styles as special cases. Style specifications
are strings of the form
An example of such a style specification is `tab-frame';
see the table in subsection 4.1.1 for more styles.
When an object asks for a brush of certain style, the selected
drawing engine will attempt to find the closest match to this
specification. The styles/brushes defined by the drawing engines
may have asterisks (`*') as some of the elements indicating
a match to anything. Exact matches are preferred to asterisk
matches and longer matches to shorter. For example, let a brush
for style `foo-bar-baz' be queried, then the following
brushes are in order of preference:
Some of the drawing primitives allow extra attributes to be
specified, also in the form
Drawing engine style files are usually named
look_foo.lua where foo is the name of the
style. The file that Notion loads on startup or when
gr.read_config is called, however, is look.lua
and should usually be symlinked to or a copy of of some
look_foo.lua.
The first thing to do in a style file is to choose the drawing
engine, possibly loading the module as well. This is done
with the following chunk of code.
The gr.select_engine function sees if the engine
given as argument is registered (the default drawing engine is
simply called ``de''). If the engine could not be found, it
tries to load a module of the same name. If the engine still
is not registered, gr.select_engine returns `false'
and in this case we also exit the style setup script.
If the engine was found, gr.select_engine sees that
further requests for brushes are forwarded to that engine
and returns `true'.
Before defining new styles it may be a good idea to clear old
styles from memory so if the old configuration defines more
specific styles than the new, the old styles don't override
those specified by the new configuration. That can be done by
calling
After this the new styles can be defined with de.defstyle
as explained in the next subsection. Finally, after the styles have
been defined we must ask objects on the screen to look up new brushes
to reflect the changes in configuration. This is done with
Styles for the default drawing engine are defined with the
function de.defstyle. It has two arguments the first being
a style specification as explained in previous sections and the second
a table whose fields describe the style:
The supported attributes are described in tables below. The different
border elements and styles referred to there are explained in the following
sketch of different border styles and elements:
Each of these fields a string of the form that can be
passed to XAllocNamedColor. Valid strings are e.g.
hexadecimal RGB specifications of the form
#RRGGBB and colour names as specified
in /usr/X11R6/lib/X11/rgb.txt (exact path varying).
All other fields below except border_style are non-negative integers
indicating a number of pixels.
As discussed in previous sections, styles may have substyles to e.g.
indicate different states of the object being drawn. The ``de'' engine
limits what can be configured in substyles to the set of colours in the
first table above, but also specifically interprets for the main style
`tab-frame' the substyles `*-*-tagged' and `*-*-*-dragged'
by, respectively, drawing a right angle shape at the top right corner
of a tab and by shading the tab with a stipple pattern. Also for
menus the substyles `*-*-submenu' are handled as a special case.
Substyles are defined with the function de.substyle within the
table defining the main style. The parameters to this function are
similar to those of de.defstyle.
The following shortened segment from look_cleanviolet.lua
should help to clarify the matters discussed in the previous
subsection.
The function WFrame.set_grattr may be used to give frames
(and their tabs) arbitrary extra attributes to be passed to the
drawing engine. Hence, by configuring such substyles in the style
configuration files, and turning on the attribute when needed,
scripts may display visual cues related to the frame. There is
also one extra attribute specially interpreted by the default
drawing engine: the `numbered' attribute, which causes
numbers to be displayed on the tabs.
The following style fields are independent of the drawing engine used,
but are related to objects' styles and therefore configured in the drawing
engine configuration file.
Hopefully that's enough to get you started in writing new style
configuration files for Notion. When in doubt, study the existing
style configuration files.
This chapter documents some additional features of the Notion configuration
and scripting interface that can be used for more advanced scripting than
the basic configuration explained in chapter 3.
Some of Notion's functions call other functions in so-called ``protected mode''.
In particular this is true for all the iterator functions mentioned in
6. If a function fn is called in protected mode, the call
will only succeed if fn is considered ``safe'', and will otherwise fail
with the message ``Ignoring call to unsafe function fn in restricted
mode.''.
Let us try to explain the rationale behind this behavior and the heuristic for
deciding when a function can be considered safe through an example. The function
WMPlex.managed_i iterates over all regions managed by an mplex and
calls iterfn on each of these regions. If iterfn was able to alter
the list of regions managed by mplex, say by adding additional regions,
this iteration could easily turn into an infinite loop or lead to inconsistent
behavior.
To avoid situations like this, in order to be considered safe, a function must
not alter any of the internal data structures of Notion.
If you ever need to use an unsafe function in combination with an iterator,
there is a simple workaround. In the example above, instead of writing
WMPlex.managed_i(mplex, iterfn), which fails if iterfn is
unsafe, you can use the following code snippet to achieve the same result:
Hooks are lists of functions to be called when a certain event occurs.
There are two types of them; normal and ``alternative'' hooks. Normal
hooks do not return anything, but alt-hooks should return a boolean
indicating whether it handled its assigned task successfully. In the case
that true is returned, remaining handlers are not called.
Hook handlers are registered by first finding the hook
with ioncore.get_hook and then calling WHook.add
on the (successful) result with the handler as parameter. Similarly
handlers are unregistered with WHook.remove. For example:
In this example the hook handler has no parameters, but many hook
handlers do. The types of parameters for each hook are listed in
the hook reference, section 6.9.
Note that many of the hooks are called in ``protected mode'' and can not
use any functions that modify Notion's internal state.
All Notion objects are passed to Lua scripts as 'userdatas', and you may
safely store such object references for future use. The C-side object
may be destroyed while Lua still refers to the object. All exported
functions gracefully fail in such a case, but if you need to explicitly
test that the C-side object still exists, use obj_exists.
As an example, the following short piece of code implements
bookmarking:
If you want to a single non-WClientWin region with an exact known
name, use ioncore.lookup_region. If you want a list of all regions,
use ioncore.region_list. Both functions accept an optional argument
that can be used to specify that the returned region(s) must be of a more
specific type. Client windows live in a different namespace and for them
you should use the equivalent functions ioncore.lookup_clientwin
and ioncore.clientwin_list.
To get the name of an object, use WRegion.name. Please be
aware, that the names of client windows reflect their titles and
are subject to changes. To change the name of a non-client window
region, use WRegion.set_name.
It is possible to write more complex winprop selection routines than
those described in section 3.5. To match a particular
winprop using whatever way you want to, just set the match
field of the winprop to a function that receives the as its parameters
the triple (prop, cwin, id), where prop is the table for
the winprop itself, cwin is the client window object,
and id is the WClientWin.get_ident result.
The function should return true if the winprop matches,
and false otherwise. Note that the match function
is only called after matching against class/role/instance.
The title of a client window can be obtained with WRegion.name.
If you want to match against (almost) arbitrary window properties,
have a look at the documentation for the following functions, and
their standard Xlib counterparts: ioncore.x_intern_atom
(XInternAtom), ioncore.x_get_window_property (XGetWindowProperty),
and ioncore.x_get_text_property (XGetTextProperty).
All statusbar meters that do not monitor the internal state of Notion should
go in the separate ion-statusd program.
Whenever the user requests a meter `%foo' or `%foo_bar' to
be inserted in a statusbar, mod_statusbar asks ion-statusd
to load statusd_foo.lua on its search path (same as that for Notion-side
scripts). This script should then supply all meters with the initial part
`foo'.
To provide this value, the script should simply call statusd.inform
with the name of the meter and the value as a string.
Additionally the script should provide a 'template' for the meter to
facilitate expected width calculation by mod_statusbar, and
may provide a 'hint' for colour-coding the value. The interpretation
of hints depends on the graphical style in use, and currently the
stock styles support the `normal', `important' and
`critical' hints.
In our example of the 'foo monitor', at script initialisation we might broadcast
the template as follows:
To inform mod_statusbar of the actual value of the meter and
indicate that the value is critical if above 100, we might write the
following function:
To periodically update the value of the meter, we must use timers.
First we must create one:
Then we write a function to be called whenever the timer expires.
This function must also restart the timer.
Finally, at the end of our script we want to do the initial
measurement, and set up timer for further measurements:
If our scripts supports configurable parameters, the following code
(at the beginning of the script) will allow them to be configured in
cfg_statusbar.lua and passed to the status daemon and our script:
The string guard maybe set to pose limits on _sub. Currently
supported guards are _sub:non-nil and _sub:WFoobar, where
WFoobar is a class.
For GUI commands, you might prefer to use mod_query.exec_on_merr(), which
monitors the process's stderr and shows any output as warnings on
the screen instead of in notions own output.
Similarly to sed's 's' command, rule may contain characters that are
inserted in the resulting string and specials as follows:
Detaching a region means having it managed by its nearest ancestor
WGroup. Reattaching means having it managed where it used
to be managed, if a ``return placeholder'' exists.
Additionally, setting how to `forget', can be used to
clear this return placeholder of the group leader of reg.
Note that this function is asynchronous; the screen will not
actually have received the focus when this function returns.
Note that this function is asynchronous; the screen will not
actually have received the focus when this function returns.
Note that this function is asynchronous; the screen will not
actually have received the focus when this function returns.
Note that this function is asynchronous; the region will not
actually have received the focus when this function returns.
When a keyboard resize function is called, and at most kbresize_t_max
milliseconds has passed from a previous call, acceleration factor is reset
to 1.0. Otherwise, if at least kbresize_t_min milliseconds have
passed from the from previous acceleration update or reset the squere root
of the acceleration factor is incremented by kbresize_step. The
maximum acceleration factor (pixels/call modulo size hints) is given by
kbresize_maxacc. The default values are (200, 50, 30, 100).
In addition parameters to the region to be created are passed in this
same table.
In addition parameters to the region to be created are passed in this
same table.
Note that this function is asynchronous; the region will not
actually have received the focus when this function returns.
I'm not *entirely* sure what 'safe' means, but this doesn't change internal
notion state, so I guess it's 'safe'...
This function is considered safe.
Note that this function is asynchronous; the selection will not
actually be inserted before Ion receives it. This will be no
earlier than Ion return to its main loop.
Any parameters not explicitly set in conftab will be left unchanged.
This hook is not called in protected mode and can be used for
arbitrary placement policies (deciding in which workspace a new
WClientWin should go). In this case, you can call
A region is pseudo-active, when a) it is itself not active (does
not not have the focus, and may not even have a window that could
have it), but b) some region managed by it is active.
Some functions accept a sizepolicy parameter. The possible
values are:
The ``free'' policies allow the managed
object to be moved around, whereas the other versions do not.
The ``glue'' policies glue the object to some border, while allowing
it to be moved away from it by user action, but not automatically.
The ``stretch'' policies stretch the object along the given border,
while the coordinate-based policies simply place the object along
that border.
The purpose of this License is to make a manual, textbook, or other
functional and useful document ``free'' in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.
This License is a kind of ``copyleft'', which means that derivative
works of the document must themselves be free in the same sense. It
complements the GNU General Public License, which is a copyleft
license designed for free software.
We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book. We recommend this License
principally for works whose purpose is instruction or reference.
This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License. Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein. The ``Document'', below,
refers to any such manual or work. Any member of the public is a
licensee, and is addressed as ``you''. You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.
A ``Modified Version'' of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
A ``Secondary Section'' is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject. (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
The ``Invariant Sections'' are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License. If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant. The Document may contain zero
Invariant Sections. If the Document does not identify any Invariant
Sections then there are none.
The ``Cover Texts'' are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License. A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.
A ``Transparent'' copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text. A copy that is not ``Transparent'' is called ``Opaque''.
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification. Examples of
transparent image formats include PNG, XCF and JPG. Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
The ``Title Page'' means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, ``Title Page'' means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
A section ``Entitled XYZ'' means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language. (Here XYZ stands for a
specific section name mentioned below, such as ``Acknowledgements'',
``Dedications'', ``Endorsements'', or ``History''.)
To ``Preserve the Title''
of such a section when you modify the Document means that it remains a
section ``Entitled XYZ'' according to this definition.
The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document. These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License. You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept
compensation in exchange for copies. If you distribute a large enough
number of copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and
you may publicly display copies.
If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
the full title with all words of the title equally prominent and
visible. You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.
It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
them a chance to provide you with an updated version of the Document.
You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it. In addition, you must do these things in the Modified Version:
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant. To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
You may add a section Entitled ``Endorsements'', provided it contains
nothing but endorsements of your Modified Version by various
parties-for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.
You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version. Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity. If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.
You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy. If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled ``History''
in the various original documents, forming one section Entitled
``History''; likewise combine any sections Entitled ``Acknowledgements'',
and any sections Entitled ``Dedications''. You must delete all sections
Entitled ``Endorsements''.
You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.
You may extract a single document from such a collection, and distribute
it individually under this License, provided you insert a copy of this
License into the extracted document, and follow this License in all
other respects regarding verbatim copying of that document.
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an ``aggregate'' if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers. In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.
If a section in the Document is Entitled ``Acknowledgements'',
``Dedications'', or ``History'', the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.
You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License. Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License. However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns. See
http://www.gnu.org/copyleft/.
Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License ``or any later version'' applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation. If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
license notices just after the title page:
If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
replace the ``with ... Texts.'' line with this:
If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.
If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
free software license, such as the GNU General Public License,
to permit their use in free software.
de.defstyle
This document was generated using the
LaTeX2HTML translator Version 2012 (1.2)
Copyright © 1993, 1994, 1995, 1996,
Nikos Drakos,
Computer Based Learning Unit, University of Leeds.
The command line arguments were:
The translation was initiated by builduser on 2016-03-09) of objects
gets to handle the action.
3.3.1 Binding handlers and special variables
Variable _ (underscore)
_sub
_chld
"_:inc_index(_sub)"
3.3.2 Guards
Guard `_sub:non-nil'
`_sub:SomeClass'
3.3.3 Defining the bindings
Mouse actions:
3.3.4 Examples
defbindings("WScreen", {
kpress("Mod1+Right", "_:switch_next()"),
kpress("Mod1+1", "_:switch_nth(1)"),
})
defbindings("WFrame", {
submap("Mod1+K", {
kpress("Right", "_:switch_next()"),
kpress("1", "_:switch_nth(1)"),
}),
})
3.3.5 Key specifications
3.3.6 Button specifications
defbindings("WFrame", {
mdrag("Button1@tab", "_:p_tabdrag()"),
})
3.3.7 A further note on the default binding configuration
3.4 Menus
3.4.1 Defining menus
defmenu("exitmenu", {
menuentry("Restart", "ioncore.restart()"),
menuentry("Exit", "ioncore.shutdown()"),
})
defmenu("mainmenu", {
menuentry("Lock screen", "ioncore.exec('xlock')"),
menuentry("Help", "mod_query.query_man(_)"),
submenu("Exit", "exitmenu"),
})
3.4.2 Special menus
Menu name `windowlist'
`workspacelist'
`focuslist'
`focuslist_'
`stylemenu'
`ctxmenu'
3.4.3 Defining context menus
defctxmenu("WFrame", {
menuentry("Close", "WRegion.rqclose_propagate(_, _sub)"),
menuentry("Kill", "WClientWin.kill(_sub)", "_sub:WClientWin"),
})
3.4.4 Displaying menus
Function mod_menu.menu
mod_menu.pmenu
mod_menu.grabmenu
defbindings("WFrame", {
kpress(MOD1.."M", "mod_menu.menu(_, _sub, 'ctxmenu')"),
mpress("Button3", "mod_menu.pmenu(_, _sub, 'ctxmenu')"),
})
3.5 Winprops
3.5.1 Properties to set
3.5.1.1 Sizehint winprops
3.5.2 Identifying windows
3.5.2.1 Classes, roles and instances
class role instance E E E
E E *
E * E
E * *
&vellip#vdots; &vellip#vdots; etc.
3.5.2.2 Secondary filters
3.5.2.3 Custom matching algorithms
3.5.3 Finding window identification
3.5.4 Some common examples
3.5.4.1 Acrobat Reader
defwinprop{
class = "AcroRead",
instance = "documentShell",
acrobatic = true,
}
3.5.4.2 Forcing newly created windows in named frames
defwinprop{
class = "XTerm",
instance = "sysmon",
target = "sysmonframe",
}
mod_query.query_renameframe(_)
3.6 Dockapps, panels and statusbars
3.6.1 The dock
3.6.2 The statusbar
-- Create a statusbar
mod_statusbar.create{
screen = 0, -- First screen,
pos = 'bl', -- bottom left corner
systray = true, -- Swallow systray windows
-- The template
template = "[ %date || load:% %>load || mail:% %>mail_new/%>mail_total ]"
.. " %filler%systray",
}
-- Launch ion-statusd.
mod_statusbar.launch_statusd{
-- Date meter
date={
-- ISO-8601 date format with additional abbreviated day name
date_format='%a %Y-%m-%d %H:%M',
},
}
3.6.2.1 The template
3.6.2.2 The systray
3.6.2.3 Monitors
3.6.2.3.1 Date
3.6.2.3.2 Load
3.6.2.3.3 Mail
$MAIL
).
files: list of additional mailboxes, the key giving the
name of the monitor.
4. Graphical styles
4.1 Drawing engines, style specifications and sub-styles
element1-element2-...-elementn
foo-bar-baz
foo-*-baz
foo-bar
*
attr1-attr2-...-attrn
These extra attributes are called substyles
and allow, for example, the state of the object to be indicated
by different colour sets while keeping the interface at an
abstract level and the drawing engine completely ignorant
of the semantics - only the writer of the drawing engine
configuration file has to know them. However the drawing
engine can again interpret known substyles as special cases
and the default engine indeed does so with frame tab
tag and drag states.)
4.1.1 Known styles and substyles
4.1.1.1 Frames
Style name `frame'
`frame-tiled'
`frame-tiled-alt'
`frame-floating'
`frame-transient'
4.1.1.2 Tabs and menu entries
Style name `tab'
`tab-frame'
`tab-frame-tiled',
`tab-frame-tiled-alt',
`tab-frame-floating',
`tab-frame-transient'
`tab-menuentry'
`tab-menuentry-bigmenu'
`tab-info'
4.1.1.3 The rest
Style name `input'
`input-edln'
`input-message'
`input-menu'
`input-menu-bigmenu'
`moveres_display'
`actnotify'
`stdisp'
`stdisp-dock'
`stdisp-statusbar'
4.2 Defining styles for the default drawing engine
4.2.1 The structure of the configuration files
if not gr.select_engine("de") then
return
end
de.reset()
gr.refresh()
4.2.2 Defining the styles
de.defstyle("some-style", {
attribute = value,
...
})
Elevated: Inlaid: Ridge: Groove:
hhhhhhhhhhhs ............ hhhhhhhhhhhs sssssssssssh
h..........s .sssssssssh. h..........s s..........h
h. .s .s h. h.sssssssh.s s.hhhhhhhs.h
h. .s .s h. h.s h.s s.h s.h
h. .s .s h. h.shhhhhhh.s s.hsssssss.h
h..........s .shhhhhhhhh. h..........s s..........h
hsssssssssss ............ hsssssssssss shhhhhhhhhhh
h = highlight, s = shadow, . = padding
4.2.2.1 Colours
Field highlight_colour
shadow_colour
foreground_colour
background_colour
padding_colour
4.2.2.2 Borders and widths
Field border_style
border_sides
highlight_pixels
shadow_pixels
padding_pixels
spacing
4.2.2.3 Text
Field font
text_align
4.2.2.4 Miscellaneous
Field transparent_background
based_on
4.2.2.5 Substyles
de.defstyle("some-style", {
...
de.substyle("some-substyle", {
...
}),
...
})
4.2.3 An example
de.defstyle("*", {
-- Gray background
highlight_colour = "#eeeeee",
shadow_colour = "#eeeeee",
background_colour = "#aaaaaa",
foreground_colour = "#000000",
shadow_pixels = 1,
highlight_pixels = 1,
padding_pixels = 1,
spacing = 0,
border_style = "elevated",
font = "-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*",
text_align = "center",
})
de.defstyle("tab-frame", {
based_on = "*",
de.substyle("active-selected", {
-- Violet tab
highlight_colour = "#aaaacc",
shadow_colour = "#aaaacc",
background_colour = "#666699",
foreground_colour = "#eeeeee",
}),
-- More substyles would follow ...
})
4.3 Miscellaneous settings
4.3.1 Frame user attributes
4.3.2 Extra fields for style `frame'
Field bar
frame_tab_width_alg
frame_tab_min_w
floatframe_tab_min_w
frame_propor_tab_min_w
floatframe_bar_max_w_q
4.3.3 Extra fields for style `dock'
Field outline_style
tile_size
5. Scripting
5.1 Protected mode and (un-)safe functions
managed_regions={}
mplex:managed_i(function(reg)
table.insert(managed_regions, reg) return true
end)
for _,reg in ipairs(managed_regions) do
iterfn(reg)
end
5.2 Hooks
ioncore.get_hook("ioncore_snapshot_hook"):add(
function() print("Snapshot hook called.") end
)
5.3 Referring to regions
5.3.1 Direct object references
local bookmarks={}
-- Set bookmark bm point to the region reg
function set_bookmark(bm, reg)
bookmarks[bm]=reg
end
-- Go to bookmark bm
function goto_bookmark(bm)
if bookmarks[bm] then
-- We could check that bookmarks[bm] still exists, if we
-- wanted to avoid an error message.
bookmarks[bm]:goto()
end
end
5.3.2 Name-based lookups
5.4 Alternative winprop selection criteria
5.5 Writing ion-statusd monitors
statusd.inform("foo_template", "000")
local function inform_foo(foo)
statusd.inform("foo", tostring(foo))
if foo>100 then
statusd.inform("foo_hint", "critical")
else
statusd.inform("foo_hint", "normal")
end
end
local foo_timer=statusd.create_timer()
local function update_foo()
local foo= ... measure foo somehow ...
inform_foo(foo)
foo_timer:set(settings.update_interval, update_foo)
end
update_foo()
local defaults={
update_interval=10*1000, -- 10 seconds
}
local settings=table.join(statusd.get_config("foo"), defaults)
6. Function reference
6.1 Functions defined in ioncore
Special $0
$1 to $9
$|
$<
$>
Field opaque_resize
warp
switchto
screen_notify
frame_default_index
dblclick_delay
kbresize_delay
kbresize_t_max
kbresize_t_min
kbresize_step
kbresize_maxacc
edge_resistance
framed_transients
float_placement_method
float_placement_padding
mousefocus
unsqueeze
autoraise
usertime_diff_current
usertime_diff_new
autosave_layout
window_stacking_request
focuslist_insert_delay
activity_notification_on_all_screens
workspace_indicator_timeout
{switchto=true}
is used.
The function returns true if all tagged regions were
succesfully attached, and false otherwisse.
6.1.1 WClientWin functions
6.1.2 WFrame functions
6.1.3 WGroup functions
Field type
name
switchto
level
modal
sizepolicy
bottom
6.1.4 WGroupCW functions
6.1.5 WGroupWS functions
Field switchto
geom
6.1.6 WHook functions
6.1.7 WInfoWin functions
6.1.8 WMPlex functions
Field type
name
switchto
unnumbered
index
level
modal
hidden
passive
pseudomodal
sizepolicy
geom
-1
-2
Field pos
fullsize
action
6.1.9 WMoveresMode functions
horizmul/vertmul effect -1 Move left/up
0 No effect
1 Move right/down
6.1.10 WRegion functions
6.1.11 WRootWin functions
6.1.12 WScreen functions
6.1.13 WTimer functions
6.1.14 WWindow functions
6.1.15 global functions
6.1.16 gr functions
6.1.17 string functions
6.1.18 table functions
6.2 Functions defined in mod_tiling
6.2.1 WSplit functions
6.2.2 WSplitInner functions
6.2.3 WSplitRegion functions
6.2.4 WSplitSplit functions
6.2.5 WTiling functions
6.3 Functions defined in mod_query
Field autoshowcompl
autoshowcompl_delay
caseicompl
substrcompl
6.3.1 WComplProxy functions
6.3.2 WEdln functions
6.3.3 WInput functions
6.4 Functions defined in mod_menu
Field scroll_amount
scroll_delay
6.4.1 WMenu functions
6.5 Functions defined in mod_dock
6.5.1 WDock functions
Key Values name string
pos string in
{t, m, b}×{t, c, b}
grow up/down/left/right
is_auto bool
6.6 Functions defined in mod_sp
6.7 Functions defined in mod_statusbar
Variable Type
template string
pos string
screen integer
fullsize boolean
systray boolaen
6.7.1 WStatusBar functions
6.8 Functions defined in de
6.9 Hooks
Field Type switchto bool
jumpto bool
userpos bool
dockapp bool
maprq bool
gravity number
geom table
tfor WClientWin
reg:attach(cwin)
where reg is the region where the window should go, and
cwin is the first argument of the function added to the
hook.
Field Type reg WFrame
mode string
sw bool
sub WRegion
This hook is just for placing within a given workspace after the
workspace has been decided by the default workspace selection
policy. It is called in protected mode. For arbitrary placement
policies, clientwin_do_manage_alt should be used; it
isn't called in protected mode,
Field Type tiling WTiling
reg WRegion
mp table
res_frame WFrame
String deinit
activated
inactivated
activity
sub_activity
name
unset_manager
set_manager
tag
pseudoactivated
pseudoinactivated
6.10 Miscellaneous
6.10.1 Size policies
A. GNU Free Documentation License
Copyright © YEAR YOUR NAME.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled ``GNU
Free Documentation License''.
with the Invariant Sections being LIST THEIR TITLES, with the
Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
B. Full class hierarchy visible to Lua-side
Obj
|-->WHook
|-->WTimer
|-->WMoveresMode
|-->WRegion
| |-->WClientWin
| |-->WWindow
| | |-->WRootWin
| | |-->WMPlex
| | | |-->WFrame
| | | `-->WScreen
| | |-->WInfoWin
| | | `-->WStatusBar (mod_statusbar)
| | |-->WMenu (mod_menu)
| | `-->WInput (mod_query)
| | |-->WEdln (mod_query)
| | `-->WMessage (mod_query)
| |-->WGroup
| | |-->WGroupWS
| | `-->WGroupCW
| `-->WTiling (mod_tiling)
`-->WSplit (mod_tiling)
|-->WSplitInner (mod_tiling)
| `-->WSplitSplit (mod_tiling)
| `-->WSplitFloat (mod_tiling)
`-->WSplitRegion (mod_tiling)
`-->WSplitST (mod_tiling)
List of functions
de.defstyle_rootwin
de.reset
de.substyle
export
gr.read_config
gr.refresh
gr.select_engine
ioncore.aboutmsg
ioncore.activity_first
ioncore.activity_i
ioncore.bdoc
ioncore.chdir_for
ioncore.clientwin_i
ioncore.compile_cmd
ioncore.create_timer
ioncore.create_ws
ioncore.current
ioncore.defbindings
ioncore.defctxmenu
ioncore.defer
ioncore.deflayout
ioncore.defmenu
ioncore.defshortening
ioncore.defwinprop
ioncore.detach
ioncore.exec
ioncore.exec_on
ioncore.find_manager
ioncore.find_screen_id
ioncore.focushistory_i
ioncore.get
ioncore.getbindings
ioncore.getctxmenu
ioncore.get_dir_for
ioncore.get_hook
ioncore.getlayout
ioncore.getmenu
ioncore.get_paths
ioncore.get_savefile
ioncore.getwinprop
ioncore.goto_activity
ioncore.goto_first
ioncore.goto_next
ioncore.goto_next_screen
ioncore.goto_nth_screen
ioncore.goto_previous
ioncore.goto_prev_screen
ioncore.is_i18n
ioncore.kpress
ioncore.kpress_wait
ioncore.load_module
ioncore.lookup_clientwin
ioncore.lookup_region
ioncore.lookup_script
ioncore.match_winprop_dflt
ioncore.mclick
ioncore.mdblclick
ioncore.mdrag
ioncore.menuentry
ioncore.mpress
ioncore.navi_first
ioncore.navi_next
ioncore.popen_bgread
ioncore.profiling_start
ioncore.profiling_stop
ioncore.progname
ioncore.read_savefile
ioncore.refresh_stylelist
ioncore.region_i
ioncore.request_selection
ioncore.resign
ioncore.restart
ioncore.restart_other
ioncore.rootwin
ioncore.screens_updated
ioncore.set
ioncore.set_paths
ioncore.set_selection
ioncore.shutdown
ioncore.snapshot
ioncore.submap
ioncore.submap_enter
ioncore.submap_wait
ioncore.submenu
ioncore.tabnum.clear
ioncore.tabnum.show
ioncore.tagged_attach
ioncore.tagged_clear
ioncore.tagged_first
ioncore.tagged_i
ioncore.TR
ioncore.unsqueeze
ioncore.update_net_state
ioncore.version
ioncore.warn
ioncore.warn_traced
ioncore.write_savefile
ioncore.x_change_property
ioncore.x_delete_property
ioncore.x_get_atom_name
ioncore.x_get_text_property
ioncore.x_get_window_property
ioncore.x_intern_atom
ioncore.x_set_text_property
ioncore.x_set_utf8_property
mod_dock.set_floating_shown_on
mod_menu.get
mod_menu.grabmenu
mod_menu.menu
mod_menu.pmenu
mod_menu.set
mod_query.defcmd
mod_query.get
mod_query.history_clear
mod_query.history_get
mod_query.history_push
mod_query.history_search
mod_query.history_table
mod_query.message
mod_query.popen_completions
mod_query.query
mod_query.query_attachclient
mod_query.query_editfile
mod_query.query_exec
mod_query.query_gotoclient
mod_query.query_lua
mod_query.query_man
mod_query.query_menu
mod_query.query_renameframe
mod_query.query_renameworkspace
mod_query.query_restart
mod_query.query_runfile
mod_query.query_shutdown
mod_query.query_ssh
mod_query.query_workspace
mod_query.query_yesno
mod_query.set
mod_query.show_about_ion
mod_query.show_tree
mod_query.warn
mod_sp.create_scratchpad
mod_sp.is_scratchpad
mod_sp.set_shown
mod_sp.set_shown_on
mod_statusbar.create
mod_statusbar.inform
mod_statusbar.launch_statusd
mod_statusbar.statusbars
mod_statusbar.terminate_statusd
mod_statusbar.update
mod_tiling.get
mod_tiling.mkbottom
mod_tiling.set
mod_tiling.untile
string.shell_safe
table.append
table.copy
table.icat
table.join
table.map
WClientWin.get_ident
WClientWin.kill
WClientWin.nudge
WClientWin.quote_next
WClientWin.xid
WComplProxy.set_completions
WDock.attach
WDock.get
WDock.resize
WDock.set
WEdln.back
WEdln.backspace
WEdln.bkill_word
WEdln.bol
WEdln.bskip_word
WEdln.clear_mark
WEdln.complete
WEdln.contents
WEdln.context
WEdln.copy
WEdln.cut
WEdln.delete
WEdln.eol
WEdln.finish
WEdln.forward
WEdln.history_next
WEdln.history_prev
WEdln.insstr
WEdln.is_histcompl
WEdln.kill_line
WEdln.kill_to_bol
WEdln.kill_to_eol
WEdln.kill_word
WEdln.mark
WEdln.next_completion
WEdln.paste
WEdln.point
WEdln.prev_completion
WEdln.set_context
WEdln.set_mark
WEdln.skip_word
WEdln.transpose_chars
WEdln.transpose_words
WFrame.is_grattr
WFrame.is_shaded
WFrame.maximize_horiz
WFrame.maximize_vert
WFrame.mode
WFrame.p_switch_tab
WFrame.p_tabdrag
WFrame.set_grattr
WFrame.set_mode
WFrame.set_shaded
WGroup.attach
WGroup.attach_new
WGroup.bottom
WGroup.managed_i
WGroup.set_bottom
WGroup.set_fullscreen
WGroupWS.attach_framed
WHook.add
WHook.listed
WHook.remove
WInfoWin.set_text
WInput.cancel
WInput.scrolldown
WInput.scrollup
WMenu.cancel
WMenu.finish
WMenu.select_next
WMenu.select_nth
WMenu.select_prev
WMenu.typeahead_clear
WMoveresMode.cancel
WMoveresMode.finish
WMoveresMode.geom
WMoveresMode.move
WMoveresMode.resize
WMoveresMode.rqgeom
WMPlex.attach
WMPlex.attach_new
WMPlex.dec_index
WMPlex.get_index
WMPlex.get_stdisp
WMPlex.inc_index
WMPlex.is_hidden
WMPlex.managed_i
WMPlex.mx_count
WMPlex.mx_current
WMPlex.mx_i
WMPlex.mx_nth
WMPlex.set_hidden
WMPlex.set_index
WMPlex.set_stdisp
WMPlex.switch_next
WMPlex.switch_nth
WMPlex.switch_prev
WMPlex.switch_to
WRegion.begin_kbresize
WRegion.current
WRegion.geom
WRegion.get_configuration
WRegion.goto
WRegion.goto_focus
WRegion.groupleader_of
WRegion.is_active
WRegion.is_activity
WRegion.is_mapped
WRegion.is_tagged
WRegion.manager
WRegion.name
WRegion.parent
WRegion.rootwin_of
WRegion.rqclose
WRegion.rqclose_propagate
WRegion.rqgeom
WRegion.rqorder
WRegion.screen_of
WRegion.set_activity
WRegion.set_name
WRegion.set_name_exact
WRegion.set_tagged
WRegion.size_hints
WRootWin.current_scr
WRootWin.warp_pointer
WScreen.id
WScreen.set_managed_offset
WSplit.geom
WSplitInner.current
WSplit.parent
WSplitRegion.reg
WSplit.rqgeom
WSplitSplit.br
WSplitSplit.dir
WSplitSplit.flip
WSplitSplit.tl
WSplit.transpose
WStatusBar.get_template_table
WStatusBar.is_systray
WStatusBar.set_systray
WStatusBar.set_template
WStatusBar.set_template_table
WStatusBar.update
WTiling.farthest
WTiling.flip_at
WTiling.managed_i
WTiling.nextto
WTiling.node_of
WTiling.set_floating
WTiling.set_floating_at
WTiling.split
WTiling.split_at
WTiling.split_top
WTiling.split_tree
WTiling.transpose_at
WTiling.unsplit_at
WTimer.is_set
WTimer.reset
WTimer.set
WWindow.p_move
WWindow.p_resize
WWindow.xid
Index
Bibliography
About this document ...
Configuring and extending Notion with Lua
Copyright © 1997, 1998, 1999,
Ross Moore,
Mathematics Department, Macquarie University, Sydney.
latex2html -show_section_numbers -short_index -local_icons -noaddress -up_url http://notion.sourceforge.net -up_title 'Notion homepage' -nofootnode -style notion.css -html_version 4.0,math,table -split 0 -dir notionconf-onepage notionconf
Footnotes