This chapter describes the advanced features of When. Some of these can be handy for everyday use too, others may require some deeper insight in what occurs under the hood in a desktop session. Anyway these features can be enabled or disabled in the applet settings, and can be safely ignored if not needed.
File and Directory Notifications¶
Monitoring file and directory changes can be enabled in the Settings dialog box. This is particularly useful to perform tasks such as file synchronizations and backups, but since file monitoring can be resource consuming, the option is disabled by default. File and directory monitoring is quite basic in When: a condition can be triggered by changes either on a file or on a directory, no filter can be specified for the change type – that is, all change types are monitored (creations, writes and deeletions), and in case of directory monitoring all files in the directory are recursively monitored. These limitations are intentional, at least for the moment, in order to keep the applet as simple as possible. Also, no more than either a file or a directory can be monitored by a condition: in order to monitor more items, multiple conditions must be specified.
As said above, this feature is optional: to make it available the
pyinotify package has to be installed. The Ubuntu package manager
can handle it (
sudo apt-get install python3-pyinotify); alternatively
pip can be used to let Python install it directly:
sudo pip3 install pyinotify (this will ensure that the latest release
is installed, but package updates are left to the user). If When is
installed via a PPA the package manager will take care to install
all the dependencies, including the optional ones.
There are also some configuration steps at system level that might have to be performed if filesystem monitoring does not work properly: when a monitored directory is big enough, the default inotify watches may fall short so that not all file changes can be notified. When a directory is under control, all its subdirectories need to be watched as well recursively, and this implies that several watches are consumed. There are many sources of information on how to increase the amount of inotify watches, and as usual StackExchange is one of the most valuables: see Kernel inotify watch limit reached for a detailed description. Consider that other applications and utilities, especially the ones that synchronize files across the network – such as the cloud backup and synchronization clients – use watches intensively. In fact When monitoring activity should not be too different from other cases.
Conditions depending on file and directory monitoring are not synchronous, and checks occur on the next tick of the applet clock. Depending tasks should be aware that the triggering event might have occurred some time before the notified file or directory change.
DBus Signal Handlers¶
Recent versions of the applet support the possibility to define system and session events using DBus. Such events can activate conditions which in turn trigger task sequences, just like any other condition. However, since this is not a common use for the When scheduler as it assumes a good knowledge of the DBus interprocess communication system and the related tools, this feature is intentionally inaccessible from the applet menu and disabled by default in the configuration. To access the DBus Signal Handler Editor dialog, the user must invoke the applet from the command line with the appropriate switch, while an instance is running in the same session:
$ when-command --show-signals
This is actually the only way to expose this dialog box. Unless the user defines one or more signal handlers, there will be no User Defined Events in the corresponding box and pane in the Conditions dialog box, and When will not listen to any other system and session events than the ones available in the Events list that can be found in the Conditions dialog box. The possibility to define such events must be enabled in the Settings dialog box, and When has to be restarted to make the option effective: before restart the user events are not available in the Conditions box, although it becomes possible to show the DBus Signal Handler Editor using the command shown above. If the appropriate setting is disabled, the above command exits without showing the editor dialog.
To define a signal to listen to, the following values must be specified in the DBus Signal Handler Editor box:
- the handler name, free for the user to define as long as it begins with an alphanumeric character (letter or digit) followed by alphanumerics, dashes and underscores
- the bus type (either Session or System bus)
- the unique bus name in dotted form (e.g.
- the path of the object that emits the signal (e.g.
- the interface name in dotted form (e.g.
- the signal name
- whether the scheduler must wait until the next clock tick to process the signal (checking Activate on next clock tick)
All these values follow a precise syntax, which can be found in the DBus documentation. Moreover, if the signal has any parameters, constraints on the parameters can be specified for the condition to be verified: given a list of constraints, the user can choose whether to require all of them or just any to evaluate to true. The tests against signal parameters require the following data:
- Value # is the parameter index
- Sub # (optional) is the index within the returned parameter, when it is either a list or a dictionary: in the latter case, the index is read as a string and must match a dictionary key
- comparison (consisting of an operator, possibly negated) specifies how
the value is compared to a test value: the supported operators are
=(equality): the operands are converted to the same type, and the test is successful when they are identical; notice that, in case of boolean parameters, the only possible comparison is equality (and the related not equality): all other comparisons, if used, will evaluate to false and prevent condition activation, and the comparison value should be either true or false
CONTAINS: the test evaluates to true when either the test string is a substring of the selected value, or the parameter is a list (or struct, or dictionary: for dictionaries it only searches for values and not for keys though), no Sub # has been specified, and the test value is in the compound value
MATCHES: the test value is treated as a regular expression and the selected value, which must be a string, matches it
<(less-than): the selected value is less than the test value (converted to the parameter inferred or introspected value type)
>(greater-than): the selected value is greater than the test value (converted to the parameter inferred or introspected value type)
- Test Value is the user provided value to compare the parameter value to: in most cases it is treated as being of the same type as the selected parameter value.
When all the needed fields for a tests are given, the test can be accepted by clicking the Update button. To remove a test line, either specify Value # and Sub # or select the line to delete, then click the Remove button. Tests are optional: if no test is provided, the condition will be enqueued as soon as the signal is emitted. If a test is specified in the wrong way, or a comparison is impossible (e.g. comparing a returned list against a string), or any error arises within a test, the test will evaluate to false and the signal will not activate any associated condition. For now the tests are pretty basic: for instance nested compound values (e.g. lists of lists) are not treated by the testing algorithm. The supported parameter types are booleans, strings, numerals, simple arrays, simple structures, and simple dictionaries. Supporting more complex tests is beyond the scope of a limited scheduler: the most common expected case for the DBus signal handler is to catch events that either do not carry parameters or carry minimal information anyway.
When the system or session do not support a bus, path, interface, or signal, the signal handler registration fails: in this case the associated event never takes place and it is impossible for any associated condition to be ever verified.
By default When defines one or two environment variables when it spawns subprocesses, respectively in command based conditions and in tasks. These variables are:
WHEN_COMMAND_TASKcontaining the task name
WHEN_COMMAND_CONDITIONcontaining the name of the triggering or current condition
When the test subprocess of a command based condition is run, only
WHEN_COMMAND_CONDITION is defined, on the other hand when a task is run
both are available. This feature can be disabled in the configuration file or
in the Settings dialog box if the user doesn’t want to clutter the
environment or the variable names conflict with other ones. Please note that
in a task these variables are defined only if the task is set to import
the environment (which is true by default): if not, it will only know the
variables defined in the appropriate list. 
Item Definition File¶
In recent releases another way to define items (tasks, conditions and especially signal handlers) has been introduced, that uses text files whose syntax is similar (although it differs in some ways) to the one used in common configuration files. Roughly, an item definition file has the following format:
[NameOf_Task-01] type: task command: do_something environment variables: SOME_VAR=some appropriate value ANOTHER_VAR=42 check for: failure, status, 2 [ThisIs_Cond02] type: condition based on: file_change watched path: /home/myaccount/Documents task names: NameOf_Task-01 [SigHandler_03] type: signal_handler bus: session bus name: org.ayatana.bamf object path: /org/ayatana/bamf/matcher interface: org.ayatana.bamf.matcher signal: RunningApplicationsChanged parameters: 0:1, not equal, BoZo # this is the end of the file.
where the names in square brackets are item names, as they appear in the applet dialog boxes. Such names are case sensitive and follow the same rules as the related Name entries in dialog boxes: only names that begin with an alphanumeric character and continue with alphanumerics, underscores and dashes (that is, no spaces) are accepted. Entries must be followed by colons and in case of entries that support lists the lists must be indented and span multiple lines. Complex values are rendered using commas to separate sub-values. The value for each entry is considered to be the string beginning with the first non-blank character after the colon.
Even a single error, be it syntactical or due to other possibly more
complex discrepancies, will cause the entire file to be rejected. The
loading applet will complain with an error status and, if invoked using
--verbose switch, a very brief error message: the actual cause
of rejection can normally be found in the log files.
For each item, the item name must be enclosed in square brackets, followed
by the entries that define it. An entry that is common to all items is
type: the type must be one of
signal_handler. Every other value will be discarded and invalidate
the file. The following sections describe the remaining entries that can
(or have to) be used in item definitions, for each item type. Entry names
must be written in their entirety: abbreviations are not accepted.
Tasks are defined by the following entries. Some are mandatory and others are optional: for the optional ones, if omitted, default values are used. Consider that all entries correspond to entries or fields in the Task Definition Dialog Box and the corresponding default values are the values that the dialog box shows by default.
command: The value indicates the full command line to be executed when the task is run, it can contain every legal character for a shell command. This entry is mandatory: omission invalidates the file.
environment variables: A multi-value entry that includes a variable definition on each line. Each definition has the form
VARNAME=value, must be indented and the value must not contain quotes. Everything after the equal sign is considered part of the value, including spaces. Each line defines a single variable.
import environment: Decide whether or not to import environment for the command that the task runs. Must be either
false. Defaults to true.
startup directory: Set the startup directory for the task to be run. It should be a valid directory.
check for: The value of this entry consists either of the word
nothingor of a comma-separated list of three values, that is
outcome, source, valuewhere
sourceis one of
valueis a free form string (it can also contain commas), which should be compatible with the value chosen for
source– this means that in case
statusis chosen it should be a number.
By default, as in the corresponding dialog box, if this entry is omitted the task will check for success as an exit status of
exact match: Can be either
trueor false. If
truein the post-execution check the entire stdout or stderr will be checked against the value, otherwise the value will be sought in the command output. By default it is false. It is only taken into account if
check foris specified and set to either stdout or stderr.
regexp match: If
truethe value will be treated as a regular expression. If also
exact matchis set, then the regular expression is matched at the beginning of the output. By default it is false. It is only taken into account if
check foris specified and set to either stdout or stderr.
case sensitive: If
truethe comparison will be made in a case sensitive fashion. By default it is false. It is only taken into account if
check foris specified and set to either stdout or stderr.
Signal handlers are an advanced feature, and cannot be defined if they are not enabled in the configuration: read the appropriate section on how to enable user defined events. If user events are enabled, the following entries can be used:
bus: This value can only be one of
system. It defaults to session, so it has to be specified if the actual bus is not in the session bus.
bus name: Must hold the unique bus name in dotted form, and is mandatory.
object path: The path to the objects that can issue the signal to be caught: has a form similar to a path and is mandatory.
interface: It is the name of the object interface, in dotted form. Mandatory.
signal: The name of the signal to listen to. This too is mandatory.
defer: If set to
true(the default), the signal will be caught but the related condition will be fired at the next clock tick instead of immediately.
parameters: This is a multiple line entry, and each parameter check must be specified on a single line. Each check has the form:
idx[:sub], compare, valuewhere
idx[:sub]is the parameter index per DBus specification, possibly followed by a subindex in case the parameter is a collection.
idxis always an integer number, while
subis an integer if the collection is a list, or a string if the collection is a dictionary. The interpunction sign is a colon if the subindex is present.
compareis always one of the following tokens:
contains. It can be preceded by the word
notto negate the comparison.
valueis an arbitrary string (it can also contain commas), without quotes.
verify: Can be either
any. If set to
any(the default) the parameter check evaluates to true if any of the provided checks is positive, if set to
allthe check is true only if all parameter checks are verified. It is only taken into account if
If user events are not enabled and a signal handler is defined, the item definition file will be invalidated.
Conditions are the most complex type of items that can be defined, because of the many types that are supported. Valid entries depend on the type of condition that the file defines. Moreover, conditions depend on other items (tasks and possibly signal handlers) and if such dependencies are not satisfied the related condition – and with it the entire file – will be considered invalid.
The following entries are common to all types of condition:
based on: Determines the type of condition that is being defined. It must be one of the following and is mandatory:
intervalfor conditions based on time intervals
timefor conditions that depend on a time specification
commandif the condition depends on outcome of a command
idle_sessionfor condition that arise when the session is idle
eventfor conditions based on stock events
file_changewhen file or directory changes trigger the condition
user_eventfor conditions arising on user defined events: these can only be used if user events are enabled, otherwise the definition file is discarded.
Any other value will invalidate the definition file.
task names: A comma separated list of tasks that are executed when the condition fires up. The names must be defined, either in the set of existing tasks for the running instance, or among the tasks defined in the file itself.
repeat checks: If set to
falsethe condition is never re-checked once it was found positive. By default it is true.
sequential: If set to
truethe corresponding tasks are run in sequence, otherwise all tasks will start at the same time. True by default.
suspended: The condition will be suspended immediately after construction if this is true. False by default.
break on: Can be one of
nothing. In the first case the task sequence will break on first success, in the second case it will break on the first failure. When
nothingis specified or the entry is omitted, then the task sequence will be executed regardless of task outcomes.
Other entries depend on the values assigned to the
based on entry.
Interval based conditions require the following entry to be defined:
interval minutes: An integer mandatory value that defines the number of minutes that will occur between checks, or before the first check if the condition is not set to repeat.
All parameters are optional: if none is given, the condition will fire up every day at midnight.
year: Integer value for the year.
month: Integer value for month: must be between 1 and 12 included.
day: Integer value for day: must be between 1 and 31 included.
hour: Integer value for hour: must be between 0 and 23 included.
minute: Integer value for minute: must be between 0 and 59 included.
day of week: A token, one of
sunday. No abbreviations allowed.
Command based conditions accept a command line and the specification of what has to be checked. The latter is not mandatory, and defaults to expectation of a zero exit status.
command: The full command line to run: this is mandatory.
check for: Somewhat similar to the same entry found in Tasks, this entry must be specified as a comma-separated pair of the form
source, value, where
sourceis one of
valueis an integer in the
statuscase, or a string to look for in the other cases. Defaults to
match regexp: If
truethe test value is treated as a regular expression. Defaults to
exact match: If
truethe test value is checked against the full output (if
truethe regular expression is matched at the beginning of the output). Defaults to
case sensitive: If
truethe comparison will be case sensitive. Defaults to
The only parameter is mandatory:
idle minutes: An integer value indicating the number of minutes that the machine must wait in idle state before the condition fires.
This condition type requires a sigle entry to be defined.
event type: This must be one of the following words:
Each of them is a single word with underscores for spaces. Abbreviations are not accepted. Any other value invalidates the condition and the file.
File and Path Modifications¶
Also in this case a single entry is required, indicating the file or path that When must observe.
watched path: A path to be watched. Can be either the path to a file or to a directory. No trailing slash is required, but it has to be a full path (it could be relative if the user is sure of where When is launched from).
In this case a single entry is required and must contain the name of an user defined event. The event can either be defined in the same file or already known to the applet, but it must be defined otherwise the file fails to load. Names, as usual, are case sensitive.
event name: The name of the user defined event.
Items defined in an items definition file, just as items built using the applet GUI, will overwrite items of the same type and name.
Exporting and Importing Items¶
When saves tasks, conditions and signal handlers in binary form for use across sessions. It might be useful to have a more portable format at hand to store these items and be sure, for instance, that they will be loaded correctly when upgrading When to a newer release. While every effort will be made to avoid incompatibilities, there might be cases where compatibility cannot be kept.
To export all items to a file, the following command can be used:
$ when-command --export [filename.dump]
where the file argument is optional. If given, all items will be saved
to the specified file, otherwise in a known location in
saved file is not intended to be edited by the user – it uses a JSON
representation of the internal objects.
To import items back to the applet, it has to be shut down first and the following command must be run:
$ when-command --import [filename.dump]
filename.dump parameter must correspond to a file previously
generated using the
--export switch. If no argument is given, When
expects that items have been exported giving no file specification to the
--export switch. After import When can be restarted.
|||This behavior is intentional, since if the user chose not to import the surrounding environment, it means that it’s expected to be as clean as possible.|