mds -- The avant-garde micro-display server
*******************************************

Copyright © 2014, 2015 Mattias Andrée (maandree@member.fsf.org)

     Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''.

Overview
********

mds (mds stands for micro-display server.) is a display server protocol and an implementation of said protocol. What makes mds stand out is its core design choice: it is desigend just like a microkernel. Rather than one, possibly modular, process --- a monolithic process --- mds is comprised of many small servers, each exchangable and responsible for one thing.

mds's goal is neither security, performance nor a perfect graphical experience. mds is all about flexibility and freedom 0 (The freedom to run the program as you wish, for any purpose.).

The reason for having a display server architectured as a microkernel is so that components can be added, removed, updated and replaced online. Additionally, the message passing between the servers makes it easy to design a system that lets you make clients that can listen on messages between the servers and perhaps modify them. This enables you to do so much more with your display server. Moreover, if a single part of the system crashes it does not bring down the whole system, and the crashed server can be respawned with minor side effects. mds is architectured in three layers: a microkernel, a master server and a collection of servers. And clients are actually located on the same layer as the servers, because there is no actual difference, the only thing that separates a server from a client is for what purpose you run it. mds's kernel is a minimal program that do initialisation of the display, such as giving it an index and create runtime files and directories for servers and other programs to use. Then the kernel creates a domain socket for the master server and spawns the master server and respawns it if it crashes. Because of this, if the master server crashes it will not lose its socket when it is respawned. The master server then, on its initial spawn, starts the all servers and other programs that the user have choosen and then starts accepting connections to it and coordinates messages between servers and clients. Further, separating all components into separate processes enables us to only give the servers the privileges they actually need, rather than having one program with root privileges that takes care of everything even things that do not do require any privileges.

All mds's servers, that is all running parts of mds except the kernel, are designed so that they can re-execute themself so that they can be updated online without any side effects. Servers serialises their state, saves it to RAM (in a directory created by the kernel), re-execute themself and loads their serialised state. The kernel cannot do this because when it has spawned the master server it has no reason to re-execute, its only mission is to respawn the master server it if would happen to crash. It would technically be possible to enable the kernel to re-execute but it is not worth it as there is no reason to re-execute, and doing so puts the display server at risk of crashing.

Architecture
************

Layers
======

The mds display server in architectured in three layers. The first layer is called the kernel. The kernel is responsible for acquiring a display server index (As with any display server, the system can have multiple instances of mds running at the same time.), set up environment variables to indicate which display server and display server instance is being used, create a domain socket for the display server and start the master server and restart it if it crashes, and then clean up the system when the display server closes. The kernel only responsible for creating the domain socket for communication with the display server, it is not responsible for using it, that mission falls to the master server.

The second layer is the master server. The master server has two responsibilities: coordinating message passing between other servers and clients (In mds there is no functional distinction between servers and clients, the distinction is purely semantic.) and starting other servers.

The third layer is the other servers and clients. protocolwise there is no specification on how they are started. But in the reference implementation of the master server, this is done by starting a shell script with the pathname ${XDG_CONFIG_HOME}/mdsinitrc and the user is responsible for providing the logic in that shell script. (Moonstruck users are allowed to implement this in C or any other language of their choosing.) These servers implements the actual functionality of the display server.

Interprocess Communication
==========================

Intrinsic to mds is a powerful interprocess communication mechanism. Servers and clients connect to the display server by connecting to a domain socket served by the master server. A server or client that has connected to the display server can do three things:

  * Request assignment of a unique ID.

  * Multicast a message.

  * Join or leave a multicast group.

Upon assignment of an ID the master server will automatically place the client in a multicast group for that specific client. This automatically multicast group assignment is done by the master server simply so you as a debugger do not forget to do so. When a client is disconnected it will send out a message to a specific multicast group that the client, refered to by it's ID, have closed.

A message in the mds protocol is comprised of two parts: headers and a payload. When a client joins a multicast group it is actually saying that it is interested in receiving broadcasts containing a specific header or a specific header--value pair, or that it is interesting in all messages (This could be used for logging, possibly spying and networking.). Thus a message is automatically multicasted to groups indicated by its headers.

The multicast groups and receiving of message is called interceptions. The interesting property of interceptions is that they may be modifying. When a server registers for message interception it can say that it wants to be able to modify messages. If this is done and the server receives a message for which it has said it want to be able to modify it, the master server will wait for that server to respond before it send the message to the next server in the interception list. The server can choose to do three things with a message that it has opted in for modification of: leave the message as-is, modify the message, or consume the message. A message consumption is done by modify the message to make it empty. A consumed message will not be send to any further clients or servers in the interception list.

To make this mechanism sensible, a server or client can set a priority when it registers for interception (does not need to be modifying.) When a message is broadcasted it will be received by all servers in the interception except the original sender, unless it gets consumes. The order in which the master server sends the message to the recipients is determined by priority the servers registed with. The message first sent to the recipients with highest priority and last to the recipients with lowest priority, and ordered by the priority between those priorities. Of two or more servers have the same priority the order in which they will receive the message, of those recipients, is arbitrary.

An interesting property of this mechanism is demonstrated in the mds-vt server. Unlike most servers mds-vt maintains two concurrent connections to the display. Once mds-vt receives a signal from the OS kernel requesting to switch virtual terminal, mds-vt will from one of its connections send out a message and wait for it to be received in its other connection and the let the OS kernel switch virtual terminal. The secondary connection to the display has registered interception with lower priority of the message than the primary connection broadcasts. This message will be received by other servers that will let the message continue to the next server in the interception list once that server is ready for the OS kernel to switch virtual terminal. All of these servers have registered modifying interception of the message but none of them will actually modify or consume the message; it is only used a mechanism for letting mds-vt know when all servers are ready for the switch without having to know how many they are and wait for a reply from all of them.

Application Design
******************

When creating graphical mds applications, there are some guildlines you should follow.

  * Do not create client-side decoration. Some users do not want decorations or wants minimal decorations. Windows should look similar, server-side decoration helps ensure this. Your client-side decorations may not meet the requirements the users have. For example, your client-side decoration may only support minimise, maximise and close, whilst the user may also want, as provided by her decoration server, stick, shade and always on top. And it should be sufficient to configure your decorations once rather once for every toolkit. Additionally, because of oversight from developers, client-side decoration tends to work poorly with tiling window managers.

  * Do not remember size and position. Some users do not want their programs to remember their size and position. There is also a risk that your mechanism for implementing this does not account for the possibility that outputs may have been removed, resized or relocated. mds-posmem can be used if the user wants programs to start where they were closed the last time they were closed.

Protocol
********

Environment Variables
=====================

A crucial task of any display server is letting child processes know which display server they should connect to. X.org does this by setting the environment variable DISPLAY to <host>:<display index>, where <host> is empty if the display is one the local machine. In this tradition mds does the same thing with the environment variable MDS_DISPLAY.

mds also creates a new process group and export the new process group ID to the environment variable MDS_PGROUP. This process group can be used to send signals to all mds servers collectively.

Signals
=======

mds servers can re-execute into an updated version of their binary. This can be used to update display server online after a new version has been installed. To do this send the signal SIGUSR1 to the server you want update. If a server does not support online updating it will ignore this signal. If the operating system defines a signal named SIGUPDATE, this signal is used instead of SIGUSR1.

If you need servers to free up allocated memory that they do not use, send the signal SIGDANGER, or if not defined SIGRTMIN + 1. Unimportant servers may choose to die on SIGDANGER.

Server may also choose to support the signal SIGINFO, or if not defined SIGRTMIN + 2. It is not expected that server do support this signal, but thay must not die when received. SIGINFO is send by a user to the server, if she wants the server to dump information about the server's state or statistics to the TTY.

All servers configured to be interrupted when the signal SIGRTMIN is received. No further action is taked. This may be used by the user to test that the program supports being interrupted. It can also be used by the server to interrupt itself from another thread.

valgrind uses SIGRTMAX for its own internal stuff. Therefore servers must not use SIGRTMAX as it is hence unavailable when running under valgrind.

Filesystem
==========

The mds kernel creates two directories for the mds servers to use: one for runtime data and one for temporary data. These directories are named by MDS_RUNTIME_ROOT_DIRECTORY and MDS_STORAGE_ROOT_DIRECTORY, respectively, by the header file <libmdsserver/config.h>. If the systems runtime data directory is /run and transient temporary data directory is /tmp, and the package name of mds is mds, these directories will be /run/mds and /tmp/.{system-directory}.mds, respectively. In /tmp/.{system-directory}.mds the kernel will create a directory for the display server instance named .data prefixed by the display server index. For example if the display server index is zero, temporary data may be stored in /tmp/.{system-directory}.mds/0.data

As defined by SHM_PATH_PATTERN in <libmdsserver/config.h>, when a server re-executes itself it will marshal its state to the POSIX shared memory unit named /.proc-pid-%ji, where %ji (%ji is the pattern in *printf functions for the data type intmax_t.) is replaced with the process ID of the server. This file will be bound to the pathname /dev/shm/.proc-pid-%ji if POSIX shared memory is stored in /dev/shm by the operating system.

In MDS_RUNTIME_ROOT_DIRECTORY the kernel will create two files. .pid and .socket, both prefixed with the display server index (0.pid and 0.socket if the display server index is 0.). The .pid file contains the process ID of the display server and is used by the kernel to figure out whether an display server index is still in use or just not properly cleaned up. Of course it can be used by any program to find the process ID of the kernel process of a display server instance. The .socket is the domain socket used for communication with the display server and its servers and clients.

Message Passing
===============

Message passing over domain sockets is the underlaying technique for communicating with the display server. To communicate with the display server in the local machine a process must connect to the domain socket created by the display server kernel as named in Filesystem.

Clients should request a unique ID when it connects to the display server. (There is seldom a reason for servers to do this.) To do this the client sends

     Command: assign-id\n
     Message ID: 0\n
     \n

where \n is an LF-line break. The value on the Message ID-line does not need to be 0, but servers and clients often start with 0 and count upwards. The value is however bound to an unsigned 32-bit integer. All message must contain this Message ID-header, otherwise the message is considered corrupt and is ignored.

The empty line signifies the end of the header list, and in this case the end of the message. But a message may contain payload beneath this empty line. To include a payload, add the header Length that says how many bytes the payload is comprised.

A header must contain a header name and header value without any trailing or leading spaces, and `: ' (colon, one regular blank space) exactly delimits the name and the value.

When the master server receives this Command: assign-id-message it will assign the client a unique ID and send it to the client. (The master server is the only server than can address the client uniquely before it has an ID, so this part can only be implement in the master server.) If the client already has an ID, it will send back that ID to the client. This response consists of two headers ID assignment and In response to, containing the client's new (or possibly already assigned) ID and the value that was in the Message ID-header, respectively. For example:

     ID assignment: 0:1\n
     In response to: 0\n
     \n

Notice that the master server never includes Message ID in message originating from it.

As seen in this example, the client ID consists of two integers delimited by a colon (`:'). Both of these integers are unsigned 32-bit integers. This is done this way because unsigned 64-bit integers are forbidden because it is not supported natively be some programming languages.

Before a client has gotten a unique client ID assigned to it, it will be `0:0'.

If a client gets disconnected from the master server, the master server will sends out a signal header message. This header will be Client closed and contain ID of the client that closed. For example:

     Client closed: 0:1\n
     \n

Be aware that if a server or client closes and does not have a unique client ID, this message will be:

     Client closed: 0:0\n
     \n

Once a client has an unique client ID assigned to it, it should always include the header Client ID in its messages. The value of Client ID should be the client's ID. If a server wants to address this client, it should include the header To with the value set to the recipient's client ID. Be aware that such message may not be sent to that recipient uniquely, any server or client is free to sign up for receive of such message, any messages or message contain any other header or header--value pair that may also be included in the header.

Interception
============

As discussed in Interprocess Communication, interception in the primary feature of mds's message passing system. Not only does it enable servers to select which message it wants to receive in order to provide it's service. It also enables clients to do anything, things that was never anticipated. As an example of its power, mds does not provide any protocol for taking screenshots or recording a session. Instead, a screenshot application signs up for messages passed between the compositor and presentation servers, and simply requests that the compositor resends the screen, a feature intended for the presentation servers. A screen recoding application would do the same and just hang on and record all message passed between the servers.

If you want your server or client to receive all messages passed around in the display server, simply sign up for all messages:

     Command: intercept\n
     Message ID: 0\n
     \n

But if you only want messages contain the header Command, include that header in the payload of the message:

     Command: intercept\n
     Message ID: 0\n
     Length: 8\n
     \n
     Command\n

It is allowed to include multiple headers. You can also be more strict, and require a specific value for a header, for example:

     Command: intercept\n
     Message ID: 0\n
     Length: 16\n
     \n
     Command: get-vt\n

You may mix these two types of requirements freely. Your client will receive any message that satisfies at least one of the requirements, these requirements may be split into multiple message or coalesced into one message; but you cannot request to include receive a message if multiple requirements are satisfied.

Alternatively you can choose to stop receiving message that satisfies requirements. For example:

     Command: intercept\n
     Stop: yes\n
     Message ID: 1\n
     Length: 16\n
     \n
     Command: get-vt\n

Or stop receiving all messages:

     Command: intercept\n
     Stop: yes\n
     Message ID: 1\n
     \n

Note that this will stop you from receiving messages contain the To-header addressed to you until you request to receiving such messages again.

When you sign up for message you may request to be able to modify them before that are send to the next client in the list of client that should receive them. To do this include the header--value pair Modifying: yes:

     Command: intercept\n
     Modifying: yes\n
     Message ID: 0\n
     Length: 30\n
     \n
     Command: keyboard-enumeration\n

It is up to the client to keep track of which message that it may modify. When you receive a message that you can modify you must respond when you are done with the message.

For example, if you have signed up for Command: keyboard-enumeration with the ability to modify such messages and the message

     Command: keyboard-enumeration\n
     To: 0:1\n
     In response to: 2\n
     Message ID: 1\n
     Length: 7\n
     \n
     kernel\n

is send from a server, you may receive it as

     Command: keyboard-enumeration\n
     To: 0:1\n
     In response to: 2\n
     Message ID: 1\n
     Length: 7\n
     Modify ID: 4\n
     \n
     kernel\n

Be aware that the Modify ID may be included even if you have not signed up to be able to modify the message, it is enough that one client before you has or it was originally included  (You may however not include this header when you send out an orginal message.).

If you receive the message as such and want to add the line on-screen-keyboard-20376 to the payload should send out:  (The first line containing starting with Message ID is an example, it should be whatever is appropriate for your client.)

     Modify ID: 4\n
     Message ID: 2\n
     Modify: yes\n
     Length: 127\n
     \n
     Command: keyboard-enumeration\n
     To: 0:1\n
     In response to: 2\n
     Message ID: 1\n
     Length: 32\n
     Modify ID: 4\n
     \n
     kernel\n
     on-screen-keyboard-20376\n

If you however decide not to modify the message send out

     Modify ID: 4\n
     Message ID: 2\n
     Modify: no\n
     \n

There is also a third option: to consume to the message. This stops any further clients from receiving the message. This is done by modifying the message into an empty message:

     Modify ID: 4\n
     Message ID: 2\n
     Modify: yes\n
     \n

You may choose to include the header--value pair Length: 0, it is however redundant and discouraged.

This mechanism of being able to modify message does not make much sense unless you can control in the order the clients receive messages. This is done with what is called priority. The higher priority you have, the earlier you will receive the message. The default priority is zero, and the priority is bound to a signed 64-bit integer. If you want to be able to list yourself in Command: keyboard-enumeration message, you should sign up with a positive priority since the final recipient or requested the enumeration will receive it with priority zero. Therefore you should sign up for such message with a message like:  (4611686018427387904 is halfway to the maximium value.)

     Command: intercept\n
     Modifying: yes\n
     Priority: 4611686018427387904\n
     Message ID: 0\n
     Length: 30\n
     \n
     Command: keyboard-enumeration\n

Portability
===========

For optimal portability, there are some restrictions on protocols.

  * Because C allows unsigned integers to be encoded as either sign and magnitude, one's complement or two's complement (GCC only allows two's complement), the minimum value of any signed value with a fixed bit-size is the negative of its maximum value, that is, the minimum value int16_t is to be assumed to be -INT16_MAX (-32767) rather than INT16_MIN (-32768 with two's complement.)

  * Integers that are not especially encoded must not be larger than 64-bits if they use fixed bit-size. If, for example, size_t is 128-bits on your platform but you are using a language that only have native integers up to 64-bits you must use arbitrary size integers or otherwise make sure that the value can be properly stored and used.

  * Integer 64-bits that are not especially encoded must not be unsigned if the bit-size is fixed. This is because some programming languages primitive integers are limited to 64-bits and are signed; a large enough unsigned 64-bit integer would overflow.

  * Native endianness when a endianness is choosen. Do not assume big endianness, but the same endianness that appear on the same machine when using C.

  * All strings musts be encoded in UTF-8 without any NUL-character unless express permission is given. NUL-character may be encoded either using a zero byte or using Modified UTF-8, where it is encoded using two bytes. Which is used is selected in the protocol, however headers and their values must not include NUL-characters. No character may be encoded with more bytes than necessary. Encoding a character in extra long form is a security issue, and is prune to bugs, and is hence disallowed by newer specifications of UTF-8.

  * The new line-character is always LF ('\n', 10, line feed) and never a combination of LF and any other character, or multiple LF:s.

Utilities
*********

mds-respawn
===========

mds-respawn is a hyposerver, that is, a utility beneath servers, and intended to be used in ${XDG_CONFIG_HOME}/mdsinitrc. It will spawn a selected set of servers. If a server it spawns exits with a bad status, mds-respawn will respawn it. mds-respawn supports two options in the command line:

--alarm=SECONDS
     Schedule mds-respawn to die in SECONDS seconds. At most 1 minute.

--interval=SECONDS
     Spawned servers that die twice within SECONDS seconds should stop respawning until the signal SIGUSR2 is send to mds-respawn. At most 1 minute.

Commands for servers to spawn are specified within curly braces. Each of the braces must be alone its its own argument. For example:

     mds-respawn --interval=5       \
       { mds-foo --initial-spawn }  \
       { mds-bar --initial-spawn }  &

will spawn and supervise the servers mds-foo and mds-bar. Both spawned with the argument --initial-spawn. When a server is respawed by mds-respawn, --initial-spawn in its argument list will be replaced by --respawn to let the server know it is being respawned.

A server is considered to exit with a failure status unless it exits with the return value 0 or is terminated by the signal SIGTERM.

mds-reg
=======

mds-reg is a utility that can be used to list available protocols provided by running servers. It can also wait for a set of protocols to become available. To list all available protocols run mds-reg --list. And to wait for the protocol foo run mds-reg --wait=foo. To also wait for the protocol bar run mds-reg --wait=foo,bar or mds-reg --wait=foo --wait=bar. Both of thesestyles can be mixed if you want to wait for even more protocols.

mds-clip
========

mds-clip is a utility that can be used to review the clipboards on the display and manipulate them. mds-clip recognises the following options:

--push
     Push non-option arguments from the command line into the clipboard.

--expire=SECONDS
     Can be used with --push. The clip will not removed after SECONDS seconds.

--pop
     Pop items from the clipboard whose indices are listed in the command line as non-option arguments. The first index is 1.

--clear
     Pop all items in the clipboard.

--list
     List items in the clipboard whose indices are listed in the command line as non-option arguments. The first index is 1. If no indicies are specified, all clips will be listed.

--size
     Print the size of the clipboard, the number of clips in the clipboard.

--capacity
     Print the capacity of the clipboard, the number of clips the clipboard can hold. If both --size and --capacity is used, the size will be printed on the first line and the capacity will be printed on the second line.

--resize=CAPACITY
     Change the capaciy of the clipboard to CAPACITY clips.

--stdin
     Can be used with --push. If used, the clip that should be placed on the top of the clipboard stack should be read from stdin.

--delimiter=DELIMITER
     Can be used with --stdin or --list. If used with --stdin, an line containing only DELIMITER will delimit two values that should be placed in the clipboard. If used with --list, a line containing only DELIMITER will delimit two values in the output. The default delimiter for --list is an empty line.

-1
     Use the primary clipboard, that is, the text copy clipboard. This is the default clipboard.

-2
     Use the secondary clipboard, that is, the text selection clipboard.

-3
     Use the tertiary clipboard, that is, the non-text copy clipboard.

mds-screenshot
==============

mds-screenshot is a simple utility, and reference implementation thereof, that can take a screeenshot of either the display, a monitor, or a window with or without its decorating window. It can also include or exclude the rat cursor or gamma ramps. mds-screenshot recognises the following options:

--monitor
     Take screenshot of the monitor. The rat will be used to select monitor.

--monitor=WINDOW_ID
     Take screenshot of the monitor whose root window's window ID is WINDOW_ID or has another window in it whose window ID is WINDOW_ID.

--embed
     Take a screenshot of an embedded window. The rat will be used to select window.

--embed=WINDOW_ID
     Take a screenshot of an embedded window whose window ID is WINDOW_ID.

--window
     Take a screenshot a window. The rat will be used to select window.

--window=WINDOW_ID
     Take a screenshot of a window whose window ID is WINDOW_ID.

--decoration
     Include the window's decoration, if used together with --window. Ignored if used without --window.

--cursor
     Include the rat cursor in the screenshot.

--gamma
     Include the effects of gamma ramps in the screenshot.

--low-gamma=LOW_PRIORITY
     Include the effects of gamma ramps with a priority above LOW_PRIORITY in the screenshot.

--high-gamma=HIGH_PRIORITY
     Include the effects of gamma ramps with a priority below HIGH_PRIORITY in the screenshot. If used together with --low-gamma=LOW_PRIORITY, the range [LOW_PRIORITY, HIGH_PRIORITY] will be used.

Optionally, you can add a non-option argument that specifies the pathname of the saved file.

If neither --monitor, --embed or --window is used, a screenshot will be taked of the display. That is, all monitors.

In case of mirrored outputs, one of the potential outputs will be selected arbitrarily if --gamma, --low-gamma or --high-gamma is used. If neither is used, the screenshot will be identical for all mirrored outputs.

mds-slay
========

mds-slay a utility that can be used to kill a process by it window or identify the window ID of a window. mds-slay recognises the following options:

--embed
     Kill an embedded window. The rat will be used to select window.

--embed=WINDOW_ID
     Kill an embedded window whose window ID is WINDOW_ID.

--window
     Kill a window. The rat will be used to select window.

--window=WINDOW_ID
     Kill a window whose window ID is WINDOW_ID.

--signal=SIGNAL
     Send the signal SIGNAL to the process owning the selected window.

--no-signal
     Do not send a signal; only identify the window.

--keep-cursor
     Do not change the cursor to a kill cursor.

--print
     Print the ID of the selected window.

mds-chvt
========

mds-chvt is a utility similar to the command chvt from the kbd project. However, mds-chvt has setuid and therefore does not require root permissions, but it will only request a virtual terminal switch if the display server's virtual terminal is in the foreground. mds-chvt recognises the following options:

--switch=VT
     Switch to the virtual terminal with the index VT.

mds-kbdc
========

mds-kbdc is the program used to compile keyboard layouts and compose tables.

TODO how to use mds-kbdc

External Utilities
==================

Servers let you use the option --on-init-fork to put the process in the background when it has been initialised. This can used to spawn that depend on each other in linear order. For example, if mds-bar requires that mds-foo is initialised before it can be initialised, you can in ${XDG_CONFIG_HOME}/mdsinitrc write:

     mds-foo --on-init-fork
     mds-bar &

This will start mds-bar when mds-foo has been initialised. However if one of them crashes, that server will not respawn; to fix this mds-respawn can be used, but use of mds-respawn hinders the use of --on-init-fork. Instead you can use --on-init-sh and global semaphores. The packages, and commands, cmdipc and ipcmd can be used for this purpose. We will use cmdipc in an example:

     S=$(cmdipc -Scx set 1 | cut -d ' ' -f 2)
     # Create a System V semaphore with the value 1.

     mds-respawn { mds-foo --on-init-sh="cmdipc -Sk $S p" } &
     # Spawn `mds-foo` and decrease the semaphore with 1 when initialised.

     cmdipc -Sk $S z            # Wait for the semaphore's value to become 0.
     cmdipc -Srk $S             # Remove the semaphore.
     mds-respawn { mds-bar } &  # Spawn `mds-bar`.

This is however seldom necessary as mds-reg can often be used instead, with more abstraction as you would only need to specify what servers need to wait for, not what they provide.

Another useful command (and package) is setpgrp. mds puts itself an all its children in a new process group. However you may want to put processes that are not mds servers or mds utilities in a separate process group. setpgrp can be used to start a process in a new process group.

Servers
*******

An mds display server instance is comprised of multiple small servers that each implements a small part of the display server's functionallity. This chapter will include all servers but the master server, mds-server and the kernel, mds, the latter of which is not actually a server.

mds-echo
========

mds-echo is a server that echos message that contain the header--value pair Command: echo. This server can be used for debugging and testing as well as to enable network heartbeats.

mds-registry
============

mds-registry is a server that keeps a registry of all protocols that are supported they the sum of all active servers. It can also be used by other servers to wait until a protocol has become available.

mds-vt
======

mds-vt is the server that acquires a virtual terminal for the display, manages virtual terminal switches and enables other servers to get access to the virtual terminal's TTY and informs them of which virtual terminal the display is located on. It also enables other servers to switch the virtual terminals mode to graphical mode or text mode.

By default mds-vt will select the next available virtual terminal for the display server. You can override this behaviour by exporting a value to the environment variable XDG_VTNR. The value must be a decimal integer of a valid virtual terminal index (Which is the same thing as a valid TTY index.). To select the virtual terminal the display was started from you can use the following code in your ~/.mdsinitrc:

     export XDG_VTNR="$(fgconsole)"

fgconsole is a part of the kbd package.

mds-clipboard
=============

mds has three clipboards, one for copied text, one for selected text, and one for non-textual data. Each of these clipboards are stacks, just like in GNU Emacs. mds-clipboard implements these clipboards and automatic removal of outdated clips. Clips can be configured to expire based on time or when its originator closes.

mds-drag
========

mds-drag is the server that implements drag-and-drop support.

mds-kkbd
========

mds-kkbd implements access to the kernel-based keyboard. It does not however implement delay and rate configurations for the kernel-based keyboard as that requires root privileges. The kernel-based keyboard is a keyboard that can be accessed by reconfiguring stdin in a TTY using ioctl and then read from stdin. mds-kkbd does not implement any keyboard layout, rather it broadcasts scancodes and keycodes. However it can remap keycodes, but not scancodes.

mds-kkbd implements control over keyboard LED:s, the indicators for locked keys. The user can remap the LED:s both while the server is running, and at launch via the command line arguments. The option --led is used to remap the LED:s. The valid LED names are num, caps and scrl, and also compose and SPARC machines. The swap, for example Caps Lock's LED and Num Lock's LED, start mds-kkbd with --led=caps=num and --led=num=caps. You can also use an index instead of a name, for example --led=caps=0, but not --led=0=caps. The index must be a non-negative integer. The server's behaviour is undefined if the used value does not map to a real LED.

mds-kkbdrate
============

mds-kkbdrate is a complemental server to mds-kkbd, it implements rate and delay control for the kernel-based keyboard.

mds-kbd
=======

mds-kbd is an alternative to mds-kkbd and mds-kkbdrate. In contrast to mds-kkbd, mds-kbd implements control over individual keybroads rather than utilising the kernels keyboard drivers to treats all keyboards a one keyboard. This server is only useful for multiseat sessions and if you otherwise actually want to handle the keyboards individually.

mds-keytrans
============

mds-keytrans is the server than translates keycodes from mds-kkbd and mds-kbd, and third-party alternatives, to characters and other attributes. It implements the keyboard's layouts including modifiers, letters, other symbols, dead keys and compose.

mds-keystick
============

mds-keystick is a server that can be used to enable sticky keys. See Sticky Keys for more information.

mds-keybounce
=============

mds-keybounce is a server that can be used to enable bounce keys. See Bounce Keys for more information.

mds-slowkey
===========

mds-slowkey is a server that can be used to enable slow keys. See Slow Keys for more information.

mds-keycue
==========

mds-keycue is a server that can be used to enable loud keys. See Loud Keys for more information.

mds-kbdbind
===========

mds-kbdbind is a server similar to xbindkeys. It can be used to run commands upon selected key combinations, for example starting dmenu or change keyboard layout. mds-kbdbind can distinguish keyboards from each other.

mds-multikey
============

mds-multikey is a server that can bind a key, key combination, or sequence their of to a sequence of keys or key combinations. For example, you could bind <super>x, y to simulate that a key Faux1 is pressed, a key that does not exist, this key press could be picked up by mds-kbdbind to enable mds-kbdbind to respond to squences rather than single keys and single key combinations. alternatively you could bind <super>x to press x a selected number of times with a short selectable delay between them; or <super>x, 5 to press x five times.

mds-rat
=======

mds-rat is a server that implements support of rat (also known as mouse) devices.

mds-ratbarrier
==============

mds-ratbarrier is a server that lets you set up barriers for the rat pointer, for example at the screen edges.

A barrier requires that the rat be moved a bit extra move it can move on to the next pixel. A barrier can be directional. A barrier can also be infinite, which blocks the rat pointer fully and it cannot pass through at all.

mds-ratbind
===========

mds-ratbind is a server similar to mds-kbdbind. However, mds-ratbind respons to rat and rat cursor actions rather than keyboard actions. It can for example be used to implement hotcorners.

mds-gestures
============

mds-gestures is a server similar to mds-ratbind. However it is specialised to respond to gestures.

mds-kbd2rat
===========

If you do not have a rat or rather use your keyboard, the server mds-kbd2rat can be used to bind keyboard actions to simulate rat actions. This server is a specialisation of mds-kbdbind, rather than spawning generic commands it broadcasts messages within the display server to move the rat cursor and click on rat buttons. mds-kbdbind could be used to do this, but mds-kbd2rat will not spawn a new process for each action. For more information see Mouse Keys.

mds-hwcursor
============

mds-hwcursor is a server that draws the rat cursor to the monitor on a plane separate from all other content on the display. In less esoteric terms, it implements a hardware cursor.

mds-swcursor
============

mds-swcursor is a server that draws the rat cursor to the monitor on the same plane as all other content on the display. In less esoteric terms, it implements a software cursor.

mds-cursorshadow
================

mds-cursorshadow is a server that can be used to decorate the rat cursor with a configurable shadow.

mds-cursorgamma
===============

mds-cursorgamma is a server you can use if you use mds-hwcursor to, if not done by the graphics driver, correct the gamma correction on the hardware cursor using software gamma ramps. This of courses works whether you are using hardware or software gamma ramps for your monitor's gamma correction. If can even be used if you do not use gamma correction, in such case, only the cursor will have its gamma corrected.

mds-hwgamma
===========

To enable gamma correction, use the server mds-hwgamma. It implements hardware gamma ramps, that is, gamma ramps assisted by hardware acceleration.

mds-swgamma
===========

If your graphics driver does not support mds-hwgamma, you can instead use mds-swgamma. It implements software gamma ramps, that is, it will modify each pixel according to the selected gamma correction before it is send to the presentation sever. To accelerate this process, mds-swgamma can tell programs how to modify its colours before sending it; the programs can then tell mds-swgamma not to apply its correction. Programs such as video players can also use this to tell the server not to apply gamma correction as that may cause the video to be played back to slowly.

mds-coopgamma
=============

mds-coopgamma is a server that can be used to enable multiple clients to manipulate the gamma ramps without stepping on each others toes. It does this by letting clients tell which priority their corrections has and use this data to chain together there modifications. For example if one program wants to apply a red filter to the display and another program wants to correct the monitors' gamma, the red filter program will send lookup tables for the gamma with high priority and the correction program will send its lookup tables with low priority. mds-coopgamma will then apply the latter lookup tables on top of the red filter. The clients can tell mds-coopgamma whether it should remove their changes when they close, or even keep them and wait for the client to restart.

mds-dcvs
========

mds-dcvs is a server than can be used to simulate defective colour vision. That is, it can for example turn the display greyscale (colour blindness) or add a filter the simulates deuteranopia or deuteranomaly. This server is intended for testing that interfaces are suitable for people with defective colour vision.

mds-colour
==========

mds-colour is a server that implements colour names, such as system colours and generic names, for example `red', whose exact colour can be configured by the user. A terminal written for mds would look up colours such as `red' and `light-red' and get the colours the terminal should use by default. Nothing is to be assumed for such colours, not even that `light-red' is in fact lighter than `dark red', or that `red' is in fact `red', only that it is the colour the user wants to see when a colour is supposed to be `red'. mds-colour will notify clients when a colour has been reconfigured, added or removed. mds-colour can be notified to reload its settings by sending SIGUSR2 to the server.

mds-dither
==========

mds-dither is a server responsible for informing clients on which two colours clients should use and how to dither them (by percent, not by pattern.) This is useful if only 16-bit colours can be used, or if only 24-colour can used but gradients between for example sRGB(255, 255, 255) and sRGB(254, 254, 254) is to be drawn.

mds-dither is gamma ramp-aware. For example, if for the red channel, 0 is mapped to 0, 1 is mapped to 3, 2 is mapped 2 and 3 is mapped to 1, but 1 and 3 requires dithering, then if 3 is requested, mds-dither will tell the client to dither 0 and 2 with 50 %, which should generate 1, but 1 and 3 has been swapped.

mds-dither holds a cache of the outputs gamma ramps to optimise performance. It will also inform clients when it is time to redither colours. This happens the gamma ramps change substantially, small changes should not trigger redithering, make it a waste of CPU time if all clients using dithering would spend time figuring out whether redithering is required.

mds-retro-crt
=============

mds-retro-crt is a server that applies filters used in the terminal emulator cool-retro-term to the whole display.

mds-state
=========

mds-state is the server that keeps tracks of the windows' state.

mds-focus
=========

mds-focus is the server focuses windows and windows' components.

mds-kill
========

mds-kill is a server that can be used to send signals to processes by identifying them by their windows. This server can also be used to simply identify the process that owns a window.

mds-screensaver
===============

mds-screensaver is a server that can be used to start a screensaver or deactive monitors when the input devices has not be used for a period of time provided that no client has disabled this. It is capable of deactiving single monitors or start a screensaver on single monitors rather than all monitors.

mds-compositor
==============

mds-compositor is the server that composes the output. It takes output of all windows and arranges it to one image per monitor and sends it to the presentation servers, such as mds-dri and mds-fb.

mds-crtc
========

mds-crtc is the server that identifies CRTC:s and provide access to them.

mds-dri
=======

mds-dri is a server that displays content using the Direct Rendering Infrastructure.

mds-fb
======

mds-fb is a server that displays content using framebuffers.

mds-endomon
===========

mds-endomon is a server that provides a logical monitor inside another monitor or cinerama, an endomonitor. This lets you for example start a single-monitor full screen game but keep a part, for example the status bar with the clock, visible. For more information, see Endomonitor.

mds-mds
=======

mds-mds is a server that displays content using another mds window. It creates a window that emulates a monitor.

mds-meta
========

mds-meta is a metadisplay server. It creates or joins a named metadisplay server, and creates an alternative value for MDS_DISPLAY. Any server connecting to this alternative MDS_DISPLAY connects to this metadisplay server. This can be used to make servers shared between display server instances.

mds-meta uses the environment variable MDS_METADISPLAY to acquire the name of the metadisplay server instance it should join or create. If MDS_METADISPLAY has not been set it is treated as having an empty string for its value which is a valid metadisplay server instance name.

mds-meta works by connecting to the running display server instance, the display, and create a new display server instance, the metadisplay. Messages passed via the metadisplay's socket is forward to the display, and messages passed to via the display to mds-meta is send to the appropriate server. mds-meta manages interception in the same way as mds-server and mds-remote.

If mds-meta creates a new metadisplay, rather than joining an existing metadisplay, it will spawn ~/.mdsmetainitrc to let you start the shared servers.

An interesting property of mds-meta is that it can be used to share servers across display servers on multiple computers. For example, if you start mds-host and mds-clipboard inside the metadisplay on your central computer, displays started on other servers can run mds-remote to connect to the metadisplay so that all computers share the same clipboard. However, this network will be centralised and not distributed, so it is not perfect.

For more information, see Metadisplay Server.

mds-seat
========

mds-seat is a server that enables seat-sandboxing. It can be used to place two users on the same machine without them interfering with each others monitors and input devices. Servers started below mds-seat become shared and servers started above mds-seat become seat-private. mds-seat can filter messages from shared servers so only the appropriate seat receives them.

mds-nest
========

mds-nest is a server that creates a new mds instance inside another mds instance. A display server inside another display server.

mds-host
========

mds-host is a server that enables servers like mds-remote running on remote machines to connect to the local machine and its display server.

mds-remote
==========

mds-remote is a server that enables you to connect extend a remote mds with your local machine. This can be used to make a display server instance span multiple computers including its monitors and input devices.

mds-xmds
========

mds-xmds is a server that translates X.org calls to mds calls. It can be used to run X.org-only programs inside mds.

mds-wmds
========

mds-wmds is a server that translates Wayland calls to mds calls. It can be used to run Wayland-only programs inside mds.

mds-mmds
========

mds-mmds is a server that translates Mir calls to mds calls. It can be used to run Mir-only programs inside mds.

mds-mdsx
========

mds-mdsx is a server that translates mds calls to X.org calls. It can be used to enable mds specific programs to run inside the X.org display servers.

mds-mdsw
========

mds-mdsw is a server that translates mds calls to Wayland calls. It can be used to enable mds specific programs to run inside the Wayland display servers.

mds-mdsm
========

mds-mdsm is a server that translates mds calls to Mir calls. It can be used to enable mds specific programs to run inside the display server Mir.

mds-posmem
==========

mds-posmem is a server that remembers where window's were positioned and their size, and moves and resizes them accordingly when they are created.

mds-decorator
=============

mds-decorator is a server that provides a simple, reference implementation of a, window decorator. This window decorator should implement snappy and sticky edges and stacking (the title bars is split into tabs with different windows that have been stacked togather.)

mds-tile
========

mds-tile is a server that provides a simple, reference implementation of a, tiling window manager.

mds-stack
=========

mds-stack is a server that provides a simple, reference implementation of a, stack window manager.

mds-desktop
===========

mds-desktop is a server that provides a simple, reference implementation of a, desktop.

mds-workspace
=============

mds-workspace is a server that provides simple, reference implementation of, workspaces.

mds-tray
========

mds-tray is a server that provides a simple, reference implementation of a, status icon tray.

Protocols
*********

Infrastructure Protocols
========================

assign-id
---------

Identifying header:
     Command: assign-id

Action:
     Assign new ID to client, or fetch current ID.

Purpose:
     Assigning ID to clients so server can respond to that client.

Compulsivity:
     Manditory, part of the core infrastructure.

Reference implementation:
     mds-server

intercept
---------

Identifying header:
     Command: intercept

Action:
     Sign up for reception of message.

Optional header: Stop
     Stop reception of messages if the value for the header Stop is yes.

Optional header: Priority
     Signed 64-bit integer of reception priority (reversed of order.)

Optional header: Modifying
     Send message asynchronously and await modification if the value for the header Modifying is yes.

Optional header: Length
     Length of the message.

Message:
     List of headers and header--value-pairs that qualifies a message for reception, all messages qualifies if this list is empty.

Purpose:
     Filter received message for clients and servers.

Purpose:
     Assigned interception order for modification of messages.

Compulsivity:
     Manditory, part of the core infrastructure.

Reference implementation:
     mds-server

register
--------

Identifying header:
     Command: register

Action:
     Register availability of a command for which you implement a service.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Conditionally required header: Length
     Length of the message. Required if Action: list is included in the headers.

Optional header: Action

     remove
          Remove availability from registry if the value of the header Action is remove.

     wait
          Wait until listed commands are available if the value of the header Action is wait. However if a protocol becomes unavailable during this wait period it will still be counted as available for this wait action.

     list
          Send a list of availability commands if the value of the header Action is list.

Conditionally optional header: Time to live
     The maximum number of seconds to wait. Available and optional if Action: wait is included in the headers.

Message:
     List of values for the header Command that you implement.

Purpose:
     Identify supported display server operations.

Purpose:
     Initialisation process synchronisation.

Compulsivity:
     Highly recommended, programs may stall a bit from time to time without it, or at initialisation depending on the program's implementation.

Reference implementation:
     mds-registry

reregister
----------

Identifying header:
     Command: reregister

Action:
     Request that all servers resends Command: register with either Action: add or without the Action-header (does the same thing.)

Purpose:
     Rebuild registry created with Command: register if the registry server crashes.

Compulsivity:
     Highly recommended, programs may think a protocol is not supported of the registry server crashes if you do not implement this in your server.

Reference implementation:
     mds-registry

error
-----

Identifying header:
     Command: error

Action:
     Notify a client about a request failure.

Required header: To
     The ID of the client that send a request that failed.

Required header: In response to
     The ID of the message whose request failed.

Required header: Error
     The errno number of the error, 0 on success if the message was not an information query. The string ``custom'' can be used if there is not errno number, optionally followed by a blank space and a number that identifies the error, this number must be positive (not zero).

Conditionally optional header: Length
     The length of the message. Available and optional if ``custom'' is used in the header Error.

Message:
     Description of the error, single line, mid-sentence case, no punctuation in the end, must not be a question but rather it must be a statement. The message shall end with a line feed.

Purpose:
     Enable keyboard layout servers to automatically set active locks when the server starts based on currently active LED:s.

Compulsivity:
     Optional.

Virtual Terminal Protocols
==========================

get-vt
------

Identifying header:
     Command: get-vt

Action:
     Get the index of the virtual terminal the server is display on.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Response:
     The server will response with the header VT index and the index of the virtual terminal the server is display on in decimal format. Additionally the server will respond with the header Active with the value yes if the VT is in the foreground or the value no if the VT is in the background.

Purpose:
     Allow programs to be aware of whether the display is in the foreground or the background.

Purpose:
     Allow programs to be aware of which VT the server is running on.

Purpose:
     Allow programs to gain access of the TTY associated with the VT such that they can use ioctl and similar calls on that TTY.

Compulsivity:
     Required.

Reference implementation:
     mds-vt

configure-vt
------------

Identifying header:
     configure-vt

Action:
     Reconfigure the virtual terminal the server is display on.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Optional header: Graphical

     yes
          Set the TTY graphical mode if the value of the header Graphical is yes.

     no
          Set the TTY text mode if the value of the header Graphical is no.

     The server implementing this protocol should not set the TTY to text mode temporarily when switching TTY. It is up to the server that set the request for graphical mode to temporarily switch to text mode when switching TTY.

Optional header: Exclusive

     yes
          The server may block other process from opening the TTY if the value of the header Exclusive is yes.

     no
          The server may not block other process from opening the TTY if the value of the header Exclusive is no.

     The server implementing this protocol should keep a counter for how many servers have requested non-exclusive mode and only switch back to exclusive mode when that counter reaches zero

Response:
     The server will response with a Command: error.

Purpose:
     Allow presentation servers to enter and leave graphical mode.

Purpose:
     Allow programs to gain access of the TTY associated with the VT such that they can use ioctl and similar calls on that TTY.

Compulsivity:
     Required.

Reference implementation:
     mds-vt

switching-vt
------------

Identifying header:
     Command: switching-vt

Action:
     Notify servers about an ongoing virtual terminal switch.

Required header: Status

     deactivating
          The kernel wants to place the display in the background if the value of the header Status is deactivating.

     activating
          The kernel wants to place the display in the foreground if the value of the header Status is activating.

Instructions:
     When a virtual terminal switch is requested the server implementing control VT switching involving the display's virtual terminal will get signaled by the kernel. Upon this signal the server should broadcast this command. All servers that need to release or acquire resouces should intercept this message with the possibility of modifying it. Once a server is ready for the VT to switch it should let the message pass to the next server by telling the master server that it is no modification to do. Once all servers are read for the switch the server that emitted this message should signal the kernel that it may switch VT. The server should detect this by setting up secondary contection to the display that intercepts this message. This connection should intercept this message with priority -2^62, all servers that need to perform actions before the switch takes place must have a priority higher than -2^62, preferably 0.

Purpose:
     Allow servers to release resources when the user switch virtual terminal before the terminal actually changes and to reacquire resources when the virtual terminal become active again.

Compulsivity:
     Required.

Reference implementation:
     mds-vt

Keyboard Protocols
==================

key-sent
--------

Identifying header:
     Command: key-sent

Action:
     Announce a keyboard input event.

Required header: Keyboard
     Any string that uniquely identifies the keyboard.

     Purpose:
          Enable multi-keyboard aware programs and give at least one keyboard per seat in a multi-seat environment.

     Note:
          mds-kkbd uses kernel to indicate that it uses the kernel and thus lumps together all keyboards.

Required header: Released

     yes
          The value of the header Released will be yes if the key was released.

     no
          The value of the header Released will be no otherwise, that is, held down or pressed.

     Note: Pause/Break is automatically released directly after it has been pressed. This is feature built into most keyboards and servers should not try to circumvent this.

Required header: Keycode
     An unsigned 14-bit integer identifying the key, may be remapped.

Optional header: Scancode
     Either an unsigned 7-bit integer or a single blank space separated trio of unsigned 7-bit integers, identifying the key. This is the scancode sent from the keyboard and optionally unified by the keyboard driver, however with the typed/released bit zeroed out. This may not be remapped.

Optional header: Modifiers
     Single blank space separated list of active modifiers:

     shift
          Shift (level 2)

     ctrl
          Control

     alt
          Alternative/Option

     altgr
          Alternative Graphic (level 3)

     lvl*
          * may be any 2^n + 1 integer with 1 < n < 20.

     super
          Super

     hyper
          Hyper

     ultra
          Ultra

     caps
          Caps (usually a lock key)

     num
          Num (usually a lock key)

     scrl
          Scroll (usually a lock key)

     top
          Top (historical)

     front
          Front (historical)

     greek
          Greek (historical)

     compose
          Compose (rare, it is usually a dead key)

     Any key that has been locked should be prefix with +, if the key has been locked by nullified with non-lock modifier it should be prefixed with a -. If no modifier is active or has been nullified, none should be used.

Optional header: Key
     A textual representation of the key that has been typed or released, as mapped by the keyboard layout.

     esc
          Escape

     f*
          F* where * is any integer.

     sysrq
          System Request/Print Screen

     scrl
          Scroll (lock)

     break
          Break/Pause

     backspace
          Backspace

     tab
          Tab

     return
          Return/Enter

     space
          Blank Space

     menu
          Application Menu

     ins
          Insert

     home
          Home

     pgup
          Page Up

     del
          Delete

     end
          End

     pgdown
          Page Down

     up
          Up arrow

     left
          Left arrow

     down
          Down arrow

     right
          Right arrow

     shift
          Shift (level 2)

     begin
          Begin (keypad 5 in nagivation mode)

     ctrl
          Control

     alt
          Alternative/Option

     altgr
          Alternative Graphic (level 3)

     lvl*
          * may be any 2^n + 1 integer with 1 < n < 20.

     super
          Super

     hyper
          Hyper

     ultra
          Ultra

     caps
          Caps (usually a lock key)

     num
          Num (usually a lock key)

     scrl
          Scroll (usually a lock key)

     top
          Top (historical)

     front
          Front (historical)

     greek
          Greek (historical)

     compose
          Compose (usually a dead key)

     hexcompose
          Hex-Compose (usually a dead key) (Used to create aribitrary characters.)

     longhexcompose
          Long Hex-Compose (usually a dead key) (Variant of hexcompose for longer codepoints.)

     modelock
          Mode Lock

     letter *
          * may be any UTF-8 encoded letter.

     Keys that lock/unlock a modifer should be suffixed with a blank space and a lock. If the key is a dead key (even the Compose key) should use dead instead. A position, either left, right, keypad or an index, followed by a blank space, should prefix any key that occurs on multiple position on the keyboard, unless it only appears on the keypad once and once not on the keypad. Keys without any meaning should be identified as unknown. Modifiers and dead keys should not affect the value.

Optional header: Characters
     UTF-8 encoded string that has been written.

Purpose:
     Enable the user to use a keyboard, physical or on-screen.

Purpose:
     Enable programs to send keys as part of a script or a reply of a recorded session.

Compulsivity:
     Highly-recommended, a computer is as good as useless without a keyboard.

Reference implementation:
     mds-kkbd, mds-kbd and mds-keytrans

enumerate-keyboards
-------------------

Identifying header:
     Command: enumerate-keyboards

Action:
     List available keyboards.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Instructions:
     This message must be consumed by the first server that receives it and implements support for it, and then send out a Command: keyboard-enumeration populated with the keyboard it provide as named in the Keyboard-header for protocols such as Command: key-sent.

Purpose:
     Make it possible for clients to list all available keyboards so that can be configured individually.

Compulsivity:
     Optional.

Reference implementation:
     mds-kkbd and mds-kbd

keyboard-enumeration
--------------------

Identifying header:
     Command: keyboard-enumeration

Action:
     Response to Command: enumerate-keyboards.

Required header: To
     The ID received under Client ID-header in the Command: enumerate-keyboards-message that triggered this message to be broadcasted

Required header: In response to
     The ID received under the Message ID-header in the Command: enumerate-keyboards-message that triggered this message to be broadcasted.

Required header: Length
     Length of the message.

Message:
     New line separated list of available keyboards.

Instructions:
     All keyboard servers should listen for this message and append all keyboards it implement to the message once recieved.

Purpose:
     Make it possible for clients to list all available keyboards so that can be configured individually.

Compulsivity:
     Required if you implement Command: enumerate-keyboards.

Reference implementation:
     mds-kkbd and mds-kbd

set-keyboard-leds
-----------------

Identifying header:
     Command: set-keyboard-leds

Action:
     Activate and deactivate LED:s on a keyboard.

Required header: Active
     LED:s that should be turned on. If a LED is listed here but not in Mask that LED should be turned on if it is off, and turned off if it is on.

     The value is a single blank space separated list of LED:s:

     num
          Num lock

     caps
          Caps lock

     scrl
          Scroll lock

     compose
          Compose

     Unsupported LED:s should be silently ignored.

Required header: Mask
     LED:s listed here that do not appear in Active should be turned off. The value of this header follows the same rules as for Active.

Optional header: Keyboard
     A string that identifies the keyboard that should be affected. If omitted all keyboard are affected.

Purpose:
     Enable keyboard layout servers to activate and deactive LED:s on the keyboard to indicate active locks.

Compulsivity:
     Optional.

Reference implementation:
     mds-kkbd, mds-kbd and mds-keytrans

get-keyboard-leds
-----------------

Identifying header:
     Command: get-keyboard-leds

Action:
     List exisiting LED:s on a keyboard and their state.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: Keyboard
     A string that identifies the keyboard that should be affected.

Response:
     The server implementing support for Command: get-keyboard-leds for the keyboard indicated by Keyboard should send a message back to the client indicated by the Client ID-header (using the To-header) with the headers:

     Active
          List of currently turned on LED:s.

     Present
          List of LED:s that the server believes to be present on the keyboards.

     Both of these headers follows the rules of the Active-header under Command: set-keyboard-leds.

Purpose:
     Enable keyboard layout servers to automatically set active locks when the server starts based on currently active LED:s

Compulsivity:
     Recommended. Required if you implement support for Command: set-keyboard-leds. If you do not support this protocol servers and clients and stall when they try to get the active LED:s.

Reference implementation:
     mds-kkbd, mds-kbd and mds-keytrans

map-keyboard-leds
-----------------

Identifying header:
     Command: map-keyboard-leds

Action:
     Remap LED:s on a keyboard.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: Length
     The length of the message.

Optional header: Keyboard
     A string that identifies the keyboard that should be affected. If omitted all keyboard are affected.

Message:
     Each line contains two single space delimited values, the first value is the LED's name, the second value is the LED's new position, either a zero-based index or the name of the LED that was originally mapped to that position. For example, num num sets the LED for Num Lock to its original position. This is equivalent to num 0 on SPARC machines and num 1 on non-SPARC machines.

          num caps
          caps num

     swaps the LED:s for Num Lock and Caps Lock. Valid LED names are num, caps and scrl, and on SPARC machines compose.

Instructions:
     The server should remap the LED:s and update their activity accordingly. The server should do this atomically.

Purpose:
     Allow the user to swap LED:s on the keyboard. Some keyboards use a non-standard layout, which can be very distracting or confusing.

Purpose:
     Allow the user to correct invalid LED mappings.

Compulsivity:
     Optional.

Reference implementation:
     mds-kkbd and mds-kbd

set-keyboard-rate
-----------------

Identifying header:
     Command: set-keyboard-rate

Action:
     Set the repeat rate and repeat delay on a keyboard.

Optional header: Rate
     A floating point value of the repeat rate, measured in cycles per second (hertz). Zero means no repeat.

Optional header: Delay
     An unsigned 16-bit integer of the number of milliseconds to wait before the first time a key is repeated. Zero means that the delay is matched with the rate, that is the reciprocal of the rate.

Optional header: Emulate

     disallow
          Always use the keyboard's built in repeat feature.

     allow
          Use the keyboard's built in repeat feature when possible, otherwise emulate the feature. But if the selected settings are close enough to what the keyboard supports, use the closed settings the keyboard supports.

     if needed
          Use the keyboard's built in repeat feature when possible, otherwise emulate the feature.

     force
          Never use the keyboard's built in repeat feature, always emulate the feature.

Optional header: Keyboard
     A string that identifies the keyboard that should be affected. If omitted all keyboard are affected.

Instructions:
     If neither of Rate, Delay and Emulate headers are used. The server should reapply the settings.

Purpose:
     Enable the user to configure the repeat rate and repeat delay on keyboards.

Compulsivity:
     Optional.

Reference implementation:
     mds-kkbd and mds-kbd

get-keyboard-rate
-----------------

Identifying header:
     Command: get-keyboard-rate

Action:
     Get the repeat rate and repeat delay on a keyboard.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: Keyboard
     A string that identifies the keyboard that should be affected.

Response:
     The server implementing support for Command: get-keyboard-rate for the keyboard indicated by Keyboard should send a message back to the client indicated by the Client ID-header (using the To-header) with the headers:

     Rate
          The current repeat rate. Same syntax as in Command: set-keyboard-rate. Set to unknown if the server does not know what the value is.

     Delay
          The current repeat delay. Same syntax as in Command: set-keyboard-rate. Set to unknown if the server does not know what the value is.

     Emulated

          yes
               The server implements the key repeat in software.

          no
               The server has set the rate on the keyboard, and lets the keyboard be responsible for the repeat. This value should also be used if the server does not support Command: set-keyboard-rate for the enquired keyboard, but is the server that should be responsible for it.

Purpose:
     Enable the user to get the current repeat rate and repeat delay on the keyboard.

Compulsivity:
     Optional. Recommended if implement support for Command: set-keyboard-rate. If you do not support this protocol servers and clients and stall when they try to get the current repeat rate and repeat delay on the keyboard.

Reference implementation:
     mds-kkbd and mds-kbd

keycode-map
-----------

Identifying header:
     Command: keycode-map

Action:
     Remap keyboard keycodes and query current mapping.

Required header: Action

     remap
          Remap keys if the value of the header Action is remap.

     reset
          Reset all mappings to identity mapping if the value of the header Action is reset.

     query
          Query mapping if the value of the header Action is query.

     Each affected server will send a message format like that of Action: remap with current mapping that are not identity mappings.

Optional header: Keyboard
     A string that identifies the keyboard that should be affected. If omitted all keyboard are affected.

Conditionally required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header. Required if Action: query is included in the headers.

Conditionally optional header: Length
     The length of the message. Available and optional if Action: remap is included in the headers.

Message:
     Each line contains two single space delimited numbers, the first number is the keycode as determined by the scancode, the second number is keycode that scancode should generate. For example, 1 1 resets Escape to be mapped to Escape, and 1 59 remaps Escape to F1, while

          1 59
          59 1

     swaps Escape and F1.

Purpose:
     Enable the user to swap or replace keys on the keyboard.

Purpose:
     Enable the user manually correct an incorrectly mapped keyboard.

Compulsivity:
     Optional.

Reference implementation:
     mds-kbd and mds-kkbd

new-keyboard
------------

Identifying header:
     Command: new-keyboard

Action:
     Announce the existance of a new keyboard.

Required header: Length
     The length of the message.

Message:
     List of strings that identifies the keyboards that have been added.

Purpose:
     Enable servers and clients to detect new keyboards.

Compulsivity:
     Recommended.

Reference implementation:
     mds-kbd and mds-kkbd

old-keyboard
------------

Identifying header:
     Command: old-keyboard

Action:
     Announce the removal of an old keyboard.

Required header: Length
     The length of the message.

Message:
     List of strings that identifies the keyboards that have been removed.

Purpose:
     Enable servers and clients to detect removal of keyboards.

Compulsivity:
     Recommended.

Reference implementation:
     mds-kbd

Clipboard Protocols
===================

clipboard
---------

Identifying header:
     Command: clipboard

Action:
     Read or manipulate a clipboard.

Required header: Level
     The clipboard level, an [1, 3] integer:

     1
          Text copied/pasted using the keyboard or a menu item. (This level is called `primary'.)

     2
          Text copied/pasted using the rat. (This level is called `secondary'.)

     3
          Data to begin with a line describing the data type. (This level is called `tertiary'.)

Required header: Action
     What to do with the clipboard:

     add
          Write the message to the clipboard if the value of the header Action is add.

     read
          Read the clipboard if the value of the header Action is read.

     clear
          Clear all entries on the selected level on the clipboard if the value of the header Action is read.

     set-size
          Shrink/grow the clipstack if the value of the header Action is set-size.

     get-size
          Read the size of the clipstack if the value of the header Action is get-size. In the reply, the server will send a message containing the headers:

          Size
               The configured maximum size of the clipstack.

          Used
               The number of elements currently in the clipstack.

Conditionally required header: Length
     Length of the message. Required if Action: add is included in the headers.

Conditionally required header: Size
     The maximum number of elements in the clipstack. Required if Action: set-size is included in the headers.

Conditionally required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header. Required if Action: read or Action: read is included in the headers, or if Action: add is included in the headers and if the header Time to live is included and has a value starting with until-death.

Conditionally optional header: Index
     The index of the item in the clipstack, starting at 0. Available and optional if the Action: read is included in the headers.

Conditionally optional header: Time to live
     The number of seconds the entry should be available before it is removed by the server, or:

     until-death
          Remove entry when the client closes.

     until-death #
          Remove entry when the client closes, or # seconds have elapsed.

     forever
          Never remove it. (This is the default.)

     The server will always remove the entry when either:

      1. it is at the bottom of the clipstack and a new entry is added to the clipstack, or

      2. Action: clear is issued for the clipstack.

     The entry will also be removed, unless Time to live: forever is used, if the server crashes or is re-executed.

     It is up to the implementation to choose when the removal actually takes place. For example, the reference implementation will pop entries that have timed out when a new entry is added, the reading on the clipstack is requested or the server is reexecuted, but another implement may choose to pop entires asynchronously using another thread or an alarm an pop when SIGALRM is received.

     Available and optional if the Action: add is included in the headers.

Message:
     The content to add to the clipboard.

Purpose:
     Enable the user to duplicate content from one process into another process without requiring those processes to be aware of eathother to any extent.

Compulsivity:
     Optional.

Reference implementation:
     mds-clipboard

clipboard-info
--------------

Identifying header:
     Command: clipboard-info

Action:
     The clipboard server sends out some information about what it is doing, such as automatically removing entires.

Included header: Event

     pop
          The value of the header Event is pop when an item in the clipstack has been removed. If the value header--value-pair is used the following headers will also be included in the message:

          Level
               The clipboard level that has been affected.

          Popped
               The index of the item in the clipstack that has been removed.

          Size
               The configured maximum size of the clipstack.

          Used
               The number of elements currently in the clipstack.

     crash
          The value of the header Event is crash when the clipboard has been reset because of a software crash.

Purpose:
     Enable clients to get notification about changes to the clipboard, that cannot trivially derived from Command: clipboard

Compulsivity:
     Optional add-on to the clipboard's functionallity.

Reference implementation:
     mds-clipboard

Status Icon Protocols
=====================

add-tray-icon
-------------

Identifying header:
     Command: add-tray-icon

Action:
     Add a status icons to the status icon tray.

     The client should keep in mind that there can be any number of trays available on the system: zero, one, two or three, …, and that it will get a response once from every tray.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: Package
     The name of the package to which the program announced the icon belongs.

Required header: Icon ID
     An ID of the icon that can be used identify the icon, icon ID:s are not unique, but the combination of a package and a icon ID should be unque and can be used to ignore already added icons and hide icons that the user has been configured to be hidden.

Required header: Title
     A title describing the icon for the user, used to configured when icons should be hidden and shown among other configuration.

Required header: Icon
     The name or pathname of an icon to use together with the title.

Response:
     Recipients will respond with a message containing the headers:

     To
          Will contain the value of the Client ID from the message that triggered this response.

     In response to
          Will contain the value of the Message ID from the message that triggered this response.

     Message ID
          Will contain a value as described in Message Passing.

     Socket
          Will contain an ID to where the icon should be embeded.

     Will send update
          The value of this header will be yes if this message will be followed by a Command: tray-update-message. Otherwise the value will be no.

Purpose:
     Enable clients to add a small icon that displays the status of programs, particularly minimised programs and services.

Compulsivity:
     Optional.

update-tray-icon
----------------

Identifying header:
     Command: update-tray-icon

Action:
     Change the status of a status icon.

Required header: Status

     hide
          Hide the icon if the value of the Status-header is hide.

     show
          Show the icon if the value of the Status-header is show.

     active
          The icon is active if the value of the Status-header is active.

     inactive
          The icon is inactive if the value of the Status-header is inactive.

Purpose:
     Enable status trays to automatically hide inactive icons.

Purpose:
     Hide icons without actually removing them.

Compulsivity:
     Required if supporting Command: add-tray-icon, only Status: hide and Status show is required.

tray-update
-----------

Identifying header:
     Command: tray-update

Action:
     Send updates about the status tray to the status icon.

Required header: Socket
     Where the icon is embedded, used to identify the affected tray.

Conditionally required header: Max colour
     The maximum colour component value, for example, if using 24-bit colour, which component will be 8-bit and the maximum value will be 255, this also applies to the alpha component. Required if either for the Colour-, Foreground- or Alpha-header are used.

Conditionally required header: Size
     The width and height, in pixels, the icon should have. Required if the Length-header is used, otherwise this header is optional.

Conditionally required header: Has alpha

     yes
          The message contains an alpha channel if the value of the Has alpha-header is yes.

     no
          The message does not contain an alpha channel if the value of the Has alpha-header is no.

     Required if the Length-header is used.

Conditionally required header: Bytes
     The number of bytes the subpixels used, for example, 24-bit colours will have this set to 1 because each subpixel has 8 bits, 48-bit colours will have this set to 2 because each subpixel has 16 bits. Allowed values are: 1, 2, 4 and 8. These values are used so that CPU:s with any endianness can be trivially used as the words sizes are guaranteed to be supported in C, and mixed/middle-endianness gets complicated if we go outside this. Required if the Length-header is used.

Conditionally optional/required header: Colour
     Single blank space-separated [0, <Max colour>] sRGB 3-tuple. Available and optional if the Length-header is not used. Required if the Foreground-header but not Length-header is used.

Conditionally optional header: Foreground
     Single blank space-separated [0, <Max colour>] sRGB 3-tuple.

Optional header: Alpha
     The opacity of the tray.

Optional header: Length
     Length of the message.

Optional header: Use urgency

     yes
          The icon tray may blink if the value of the Use urgency-header is yes.

     no
          The icon tray may not blink if the value of the Use urgency-header is no.

Message:
     Raw binary encoding of the background image, bytes are orders: row, pixel, channel (alpha, red, green, blue), subpixel value (native CPU encoding). The Alpha channel should be included but ignored if Has alpha: no, in such as it is best to set it to full.

     Example image with Bytes: 2, Has alpha: no and Size: 3:

          sRGB(x0102, 0, 0), sRGB(0, x0304, 0), sRGB(0, 0, x0506)
          sRGB(x0708, 0, 0), sRGB(0, x090A, 0), sRGB(0, 0, x0B0C)
          sRGB(x0D0E, 0, 0), sRGB(0, x0F10, 0), sRGB(0, 0, x1112)

     Encoding of example image in hexadecimal representation:

          FFFF 0102 0000 0000 FFFF 0000 0304 0000 FFFF 0000 0000 0506
          FFFF 0708 0000 0000 FFFF 0000 090A 0000 FFFF 0000 0000 0B0C
          FFFF 0D0E 0000 0000 FFFF 0000 0F10 0000 FFFF 0000 0000 1112

     Note that on a big-endian system this would be: (x86_64 computers are big-endian.)

          FF FF 02 01 0 0 0 0 FF FF 0 0 04 03 0 0 FF FF 0 0 0 0 06 05
          FF FF 08 07 0 0 0 0 FF FF 0 0 0A 09 0 0 FF FF 0 0 0 0 0C 0B
          FF FF 0E 0D 0 0 0 0 FF FF 0 0 10 0F 0 0 FF FF 0 0 0 0 12 11

     It is up to the networking servers to translate the encoding between machines. (The host translates to big-endian unless they can confirm that they have the same endianness.)

Purpose:
     Enable clients to be aware of the appearance of the tray, such as colours, transparency and background image.

Purpose:
     Enable clients to be aware of how the user wants status icons to behave.

Compulsivity:
     Optional.

new-tray
--------

Identifying header:
     Command: new-tray

Action:
     Announce the existence of a new status icon trays.

Purpose:
     Allow clients to add their status icons to status icon trays that have been added to the display after those programs have started and attempted to add their icons.

Compulsivity:
     Required if supporting Command: add-tray-icon.

Colour Protocols
================

get-gamma-info
--------------

Identifying header:
     Command: get-gamma-info

Action:
     Query gamma ramp information.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: CRTC
     The output name for the CRTC of interest.

Response:
     The server will response with a Command: error on error, on success the server will respond with a message contain the headers:

     To
          Will contain the value of the header Client ID in the message that was received by the server.

     In response to
          Will contain the value of the header Message ID in the message that was received by the server.

     Cooperative
          Whether a server like mds-coopgamma is running. That is, if priorities and classes are respected. The value with be either yes, for cooperative, or no, for non-cooperative.

     Depth
          The bit-depth of the gamma ramps. Possible values are: 8, 16, 32 och 64.

     Red size
          The number of stops in the red gamma ramp.

     Green size
          The number of stops in the green gamma ramp.

     Blue size
          The number of stops in the blue gamma ramp.

     Gamma support
          Will have one of the following values:

          yes
               It is known that gamma ramps are supported.

          no
               It is known that gamma ramps are not supported.

          maybe
               It is now known whether gamma ramps are supported.

     If Gamma support: no is send in the response, the headers Depth, Red size, Green size and Blue size may be omitted.

Purpose:
     Enable performance optimisation when manipulating gamma ramps.

Compulsivity:
     Optional. Required if your implement support for Command: get-gamma or Command: set-gamma.

Reference implementation:
     mds-hwgamma, mds-swgamma, mds-coopgamma and mds-cursorgamma

get-gamma
---------

Identifying header:
     Command: get-gamma

Action:
     Query gamma ramps.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: CRTC
     The output name for the CRTC of interest.

Required header: Coalesce
     Whether the received the full gamma ramp filter list, of the value is yes, rather than the result of them, of the value is no.

Required header: High priority
     The upper bound of the priority range of the gamma ramps to received. This is a signed 64-bit integer.

Required header: Low priority
     The lower bound of the priority range of the gamma ramps to received. This is a signed 64-bit integer.

Response:
     The server will response with a Command: error on error, on success the server will respond with a message contain the headers:

     Depth
          The bit-depth of the gamma ramps. Possible values are: 8, 16, 32 och 64.

     Red size
          The number of stops in the red gamma ramp.

     Green size
          The number of stops in the green gamma ramp.

     Blue size
          The number of stops in the blue gamma ramp.

     Tables
          The number of gamma ramp lookup tables that is included in the respone's message. This header will not necessarily be included if Coalesce: yes was used in the query, rather reference implementations will exclude it.

     These headers are included so you can make sure the no metadata for gamma ramps have changed, which could happen if the user switches between hardware and software gamma ramps. The response will also contain a Length-header and a message formatted in the same manner as for Command: set-gamma-messages. That is, assuming as an example that the gamma ramp depth is 16 bits, Coalesce: yes was used in the query, the red ramp is (1, 2, 3, 4, 5, 6), the green ramp is (17, 18, 19, 20, 21, 22, 23) and the blue ramp is (33, 34, 35, 36, 37, 38, 39, 40) then the message will be (hexadecimal representation):

          0001 0002 0003 0004 0005 0006
          0011 0012 0013 0014 0015 0016 0017
          0021 0022 0023 0024 0025 0026 0027 0028

     On a big-endian system this would be:

          01 00 02 00 03 00 04 00 05 00 06 00
          11 00 12 00 13 00 14 00 15 00 16 00 17 00
          21 00 22 00 23 00 24 00 25 00 26 00 27 00 28 00

     However if Coalesce: no was used in the query, the message will include multiple gamma ramps lookup tables. These will be in the order they are applied, that is, highest priority first. The tables will be encoded in the same way as for Coalesce: yes and they with be included without any delimiter. However, each table will be prefixed with the priority and the class. The priority will be encoded in native binary format as an int64_t and the class will be encoded as a NUL-terminated UTF-8 string

Purpose:
     Enable analysis and readings of the current gamma ramps.

Compulsivity:
     Optional. Required if your implement support for Command: get-gamma-info or Command: set-gamma.

Reference implementation:
     mds-hwgamma, mds-swgamma, mds-coopgamma and mds-cursorgamma

set-gamma
---------

Identifying header:
     Command: set-gamma

Action:
     Modify gamma ramps.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: CRTC
     The output name for the CRTC of interest.

Required header: Priority
     A signed 64-bit integer of the priority for the filter. gamma correction should use zero priority. It is preferable that search logical adjustment is sent with different priorities so other programs can insert filters between them.

Required header: Class
     A UTF-8 string that identifies the filter. It should be formatted as pkg::cmd::role. pkg should be the package name the package was installed with on the system. cmd should be the basename of the command for the program.

Required header: Lifespan
     The value may be one of the following:

     until-removal
          Remove the filter when Lifespan: remove is sent.

     until-death
          Remove the filter when the client dies.

     remove
          Remove the filter now.

Conditionally required header: Length
     The length of the message. Available and required if Lifespan: remove is not included in the message.

Message:
     The gamma ramps in binary encoding. As an example, assume the gamma ramp depth is 16 bits, the red ramp is (1, 2, 3, 4, 5, 6), the green ramp is (17, 18, 19, 20, 21, 22, 23) and the blue ramp is (33, 34, 35, 36, 37, 38, 39, 40) then the message will be (hexadecimal representation):

          0001 0002 0003 0004 0005 0006
          0011 0012 0013 0014 0015 0016 0017
          0021 0022 0023 0024 0025 0026 0027 0028

     Note that on a big-endian system this would be: (x86_64 computers are big-endian.)

          01 00 02 00 03 00 04 00 05 00 06 00
          11 00 12 00 13 00 14 00 15 00 16 00 17 00
          21 00 22 00 23 00 24 00 25 00 26 00 27 00 28 00

     It is up to the networking servers to translate the encoding between machines. (The host translates to big-endian unless they can confirm that they have the same endianness.)

     The use of binary rather than text here is chosen to increase performance for programs that try the change the adjustments fluently. For programs similar to xgamma that sets the ramps once this is however unnessary. However it does simplify the program code as one would only need to write the ramps to the message without creating a string with all stops converted and then measure the length of that string.

Response:
     The server will response with a Command: error.

Instructions:
     For optimal flexibility a system may run a server such as mds-hwgamma that applies the gamma ramps, and a server such as mds-coopgamma to let multiple programs adjust the output with their open filters that stack up. In a configuration like this, mds-coopgamma will keep track of all filters and when a modification is made it sends the grand result to mds-hwgamma, that is, what the filters together produce. To do this, mds-coopgamma listens for Command: set-gamma with priority 2^62 and modifies the message so the payload is filled with the result rather than to single filter. This modified message is then received by mds-hwgamma that listens with priority zero and applies the gamma ramps. mds-hwgamma will ignore the Priority and the Class-header, but it will respect the Lifespan-header, therefore mds-coopgamma will always modify the value of the Lifespan-header to until-removal.

Purpose:
     Enable colour output correction such as gamma correction.

Purpose:
     Enable colour output filters such colour temperature adjustments, colour invertion and dimming.

Compulsivity:
     Optional. Required if your implement support for Command: get-gamma-info or Command: get-gamma.

Reference implementation:
     mds-hwgamma, mds-swgamma, mds-coopgamma and mds-cursorgamma

list-colours
------------

Identifying header:
     Command: list-colours

Action:
     Retrieve an exhaustive list of defined colours.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Optional header: Include values

     yes
          Include the values of the colours in addition to the name of the colours.

     no
          Include only the names of the colours.

     no is used if omitted.

Response:
     The server will response with a Command: error on error, on success the server will respond with a message whose payload is a list all defined colours. Each line in the payload represents a colour. If values where not requested, each line contain, exactly, the name of the colour it lists. If however values are requested, each name will be prefixed with the number of bytes with which each channel is encoded, the red value, the green value and the blue value of the colour, each of these values will be suffixed with a single regular blank space making the format bytes red green blue name. Note that the name may contain any whitespace (Tab space is discouraged.) except a line feed. Allowed values for the byte count are 1, 2, 4 and 8.

     The payload will end with a line break unless it is empty. No empty lines will otherwise be included (unless a colours name happend to be nothing (You should not define colours whose name is of zero length or containing non-ASCII or non-printable characters.).)

Purpose:
     Enable programs to list named colours, system colours or otherwise.

Compulsivity:
     Optional. Required if your implement support for Command: get-colour or Command: set-colour.

Reference implementation:
     mds-colour

get-colour
----------

Identifying header:
     Command: get-colour

Action:
     Query the values of a defined colour.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: Name
     The name of the colour whose values you want to retrieve.

Response:
     The server will response with a Command: error on error, on success the server will respond with a message contain the headers:

     Bytes
          The number of bytes with which each channel is encoded. Allowed values are 1, 2, 4 and 8.

     Red
          The value of the red channel.

     Green
          The value of the green channel.

     Blue
          The value of the blue channel.

     If the colour is not defined, the Command: error message will return a custom error, with the message ``not defined''.

Purpose:
     Provide a central place for retrieving system colours, such as text field background, for toolkits.

Purpose:
     Provide a central place for retrieving themeable colours.

Compulsivity:
     Optional. Required if your implement support for Command: list-colours or Command: set-colour.

Reference implementation:
     mds-colour

set-colour
----------

Identifying header:
     Command: set-colour

Action:
     Change the value of a defined colour, or remove it.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: Name
     The name of the colour you want to define, modify or undefine.

Optional header: Remove

     yes
          Remove the colour definition.

     no
          Add or modify colour definition.

     no is used if omitted.

Conditionally required header: Bytes
     The number of bytes with which each channel is encoded. Allowed values are 1, 2, 4 and 8. Required unless Remove: yes is included in the headers.

Conditionally required header: Red
     The value of the red channel. Required unless Remove: yes is included in the headers.

Conditionally required header: Green
     The value of the green channel. Required unless Remove: yes is included in the headers.

Conditionally required header: Blue
     The value of the blue channel. Required unless Remove: yes is included in the headers.

Purpose:
     Provide a central place for defining system colours, such as text field background, for toolkits to use.

Purpose:
     Provide a central place for defining themeable colours.

Compulsivity:
     Optional.

Reference implementation:
     mds-colour

colour-added
------------

Identifying header:
     Command: colour-added

Action:
     Announce that a new colour has been defined.

Included header: Name
     The name of the new colour.

Included header: Bytes
     The number of bytes with which each channel is encoded.

Included header: Red
     The value of the colour's red channel.

Included header: Green
     The value of the colour's green channel.

Included header: Blue
     The value of the colour's blue channel.

Included header: Last update

     yes
          No more updates are queued.

     changes
          No more additions or deletions are queued, but modifications are queued.

     no
          More additions or deletions are queued.

Purpose:
     Supplement Command: list-colours with automatic updating.

Compulsivity:
     Optional. Recommended if your implement support for Command: list-colours.

Reference implementation:
     mds-colour

colour-removed
--------------

Identifying header:
     Command: colour-removed

Action:
     Announce when colour definition is removed.

Included header: Name
     The name of the removed colour.

Included header: Last update

     yes
          No more updates are queued.

     changes
          No more additions or deletions are queued, but modifications are queued.

     no
          More additions or deletions are queued.

Purpose:
     Supplement Command: list-colours with automatic updating.

Compulsivity:
     Optional. Recommended if your implement support for Command: list-colours.

Reference implementation:
     mds-colour

colour-changed
--------------

Identifying header:
     Command: colour-changed

Action:
     Announce when a defined colour changes value.

Included header: Name
     The name of the modified colour.

Included header: Bytes
     The number of bytes with which each channel is encoded.

Included header: Red
     The new value of the colour's red channel.

Included header: Green
     The new value of the colour's green channel.

Included header: Blue
     The new value of the colour's blue channel.

Included header: Last update

     yes
          No more updates are queued.

     no
          More changes are queued.

Instructions:
     The server must always send additions and deletions of colour definitions before modifitions, when sending multiple update.

Purpose:
     Provide a way to detect when a themeable colour, or system colour, has changed, and the program needs to be redrawn with new colours.

Compulsivity:
     Optional. Recommended if your implement support for Command: list-colours or Command: get-colour.

Reference implementation:
     mds-colour

dither
------

Identifying header:
     Command: dither

Action:
     Request output device dependent colour dithering, and inform the dither server that the colour is being dithered.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: Bytes
     The number of bytes with which each channel is encoded.

Required header: Red
     The value of the colour's red channel.

Required header: Green
     The value of the colour's green channel.

Required header: Blue
     The value of the colour's blue channel.

Response:
     The server will response with a Command: error on error, on success the server will respond with a message contain a payload describing how the colour should be dithered on each output. Each line on the payload will decribed be dithering on an output. No empty lines will required, however the payload will end with a line feed unless it is empty (It can only be empty if there are no outputs.). Each line will contain line single blank space-delimited values. These values are:

       * The number of bytes with which each channel is encoded.

       * The value of the primary colour's red channel.

       * The value of the primary colour's green channel.

       * The value of the primary colour's blue channel.

       * A floating point value describing the predominance of the primary colour. A period is used as decimal comma. This value is between 0 and 1, but cannot be zero. If the value is 1, the secondary colour is identical to the primary and no dithering is required. As an example, 0.75 means that there should be 75% of the primary colour and 25% of the secondary colour.

       * The value of the secondary colour's red channel.

       * The value of the secondary colour's green channel.

       * The value of the secondary colour's blue channel.

       * The name of the CRTC for which the line describes the colour's dithering. Note that thes value may contain whitespace.

     Note that the pattern to use of dithering is not included in the response. It is up to the client to select a pattern.

Instructions:
     The dither server should count how many times the colour's dithering has be queried, per client. It should be decremented by one request each time Command: dither-stop is received for the colour and client. When the counter reaches zero for a client, the server knows that the client is no longer displaying the dithered colour.

Purpose:
     Provide dithering for low colour-depth-output, that is gamma correction- and output filter-aware.

Purpose:
     Provide gamma correction- and output filter-aware dither for low-delta colour gradients.

Compulsivity:
     Optional. Required if your implement support for Command: redither or Command: dither-stop.

Reference implementation:
     mds-dither

dither-stop
-----------

Identifying header:
     Command: dither-stop

Action:
     Inform the dither server that a colour is no longer being dithered.

Required header: Client ID
     Your ID, provided by the ID assignment-header

Required header: Bytes
     The number of bytes with which each channel is encoded.

Required header: Red
     The value of the colour's red channel.

Required header: Green
     The value of the colour's green channel.

Required header: Blue
     The value of the colour's blue channel. in response to a Command: assign-id-header.

Purpose:
     Allow dithering server to know when a client is not longer dithering colours, or a specific colour.

Compulsivity:
     Optional. Required if your implement support for Command: dither or Command: redither.

Reference implementation:
     mds-dither

redither
--------

Identifying header:
     Command: redither

Action:
     Announce that the client needs to redither its dithered colours.

Included header: Length
     The length of the message.

Message:
     A line feed-terminated, line feed-separated list of colours that need to be dithered on the client. Each line will be formatted Bytes Red Green Blue, where each these words are replaced by the values associated with the same headers of the same name in the Command: dither message that let the dither server know that the colour is being dithered.

Purpose:
     Supplement Command: dither with automatic detection of when colours need to be redithered, without all clients needing to determine when, thus saving CPU time.

Compulsivity:
     Optional. Required if your implement support for Command: dither or Command: dither-stop.

Reference implementation:
     mds-dither

Screensaver Protocols
=====================

configure-screensaver
---------------------

Identifying header:
     Command: configure-screensaver

Action:
     Reconfigure screensaver settings, or tell the screensaver server that the screensaver may not start whilst a program is active.

Optional header: Screensaver
     The command, in POSIX shell syntax, for the command to run to start the screensaver. The screensaver server will be inactive as long as the spawn command has not exited. To disable screensaving, the value for this header should be true. This command always starts without fail, and does nothing. Which means that the a screensaver will not start, and the panic action cannot start is it would if the values as set to false. The screensaver server may choose recognise the command true as meaning that does not need to start a screensaver. It is also possible to disable screensaving via the Activate delay-header.

Optional header: Activate delay
     The number of seconds the display should be inactive before the screensaver should start. Floating points are allowed. The value 0 is discouraged, but has the same meaning as disable, which means that the screensaver should never start.

Optional header: Lock delay
     The number of seconds to wait after the screensaver starts before authentication via login passphrase is required to deactivate the screensaver. Floating points are allowed. If properly formatted, the environment variable MDS_SCREENSAVER_LOCK is set to have this value. If the value is disable, the environment variable MDS_SCREENSAVER_LOCK will be cleared, which should be interpreted by the screensaver as that it should not start the lock mechanism.

Optional header: Panic on error
     The command, in POSIX shell syntax, to run if the screensaver exits without another value than 0. If you do no want anything to happen, choose either of the values true or false. This is intended as a security measure, in case the screensaver fails to start the lock mechanism.

Optional header: DPMS
     TODO

Optional header: Inhibit

     yes
          The screensaver may not start whilst the client is connected to the server.

     no
          Undo the action set by Inhibit: yes and the same client.

Conditionally required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header. Required if Inhibit is included in the headers.

Purpose:
     Allow the user to change screensaver settings.

Purpose:
     Allow programs to stop the screensaver from starting.

Compulsivity:
     Optional.

Reference implementation:
     mds-screensaver

start-screensaver
-----------------

Identifying header:
     Command: start-screensaver

Action:
     Start the screensaver, either timed or forced.

Instructions:
     The screensaver server should broadcast this command when the display has been active for long enough for the screensaver to start. It should then intercept the message, including messages with this command that is not send from the screensaver server itself, with priority -2^63. The screensaver should be started when this message is intercepted by the screensaver server. All servers that need to perform actions before the switch takes place must have a priority higher than -2^63, preferably 0. Server that can perform their actions asynchronously should intercept the message without modifying capabilities.

Purpose:
     Allow users to force the screensaver to start.

Purpose:
     Allow the screensaver daemon to notify servers when the screensaver starts.

Compulsivity:
     Optional.

Reference implementation:
     mds-screensaver

screensaver-start-test
----------------------

Identifying header:
     Command: screensaver-start-test

Action:
     Ask servers when they last were active.

Required header: Last active
     The message broadcaster should set the value of this header to 0. Any server intercepting this message should set value to the last time (monotonic time, preferably raw) the server observed actions that means that the display is active, such as usage of the keyboard or rat. The servers should however not modify the value if the value they would set it to is lower than the already set value. Floating points are allowed.

Instructions:
     The screensaver server should broadcast this message when it thinks it can start the screensaver. It should intercept this message with priority -2^63. When intercepted it should read the Last active-header to determine the next time the screensaver is allowed to start, which means that it should add the activate delay to this value. If the calculate time is in the past, the screensaver server should broadcast the start-screensaver-message to start the screensaver.

Purpose:
     Allow the screensaver to as servers like the input device servers whether it is the for the screensaver to start, instead of needing to listening on all input devices.

Compulsivity:
     Optional.

Reference implementation:
     mds-screensaver, mds-kkbd, mds-kbd and mds-rat

Miscellaneous Protocols
=======================

echo
----

Identifying header:
     Command: echo

Action:
     Echo back a message.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Optional header: Length
     Length of the message.

Message:
     Message to echo.

Purpose:
     Debugging and testing.

Purpose:
     Network heartbeat.

Compulsivity:
     Recommended for network enabled servers.

Reference implementation:
     mds-echo

kill
----

Identifying header:
     Command: kill

Action:
     Kill and identify processes based on the their windows.

Required header: Client ID
     Your ID, provided by the ID assignment-header in response to a Command: assign-id-header.

Required header: Window ID
     The ID of the window whose owning process should be identified or signaled.

Required header: Signal
     A numerical value of the signal to send to the process. It is up to networking protocols to translate these numbers of the display spans multiple operating systems. The signal zero can usually be used if no signal is to be sent, this is however dependent on the operating system.

Response:
     The server will respond with a Command: error-message. In this message the server all include an ad-hoc header: Process ID. Its value will be the ID of the process that owns the window.

Purpose:
     Identify and send signal to processes by refering to them by one of their windows.

Compulsivity:
     Optional.

Reference implementation:
     mds-kill and mds-slay

libmdsserver
************

libmdsserver is library written for the reference implementation of the mds servers. llibmdsserver does not contain support for any protocols, rather it contains auxiliary functions, macros, data structures such as linked lists and hash tables, and support the basics of the message passing protocol: receiving message and decode it into headers and payloads.

Macros
======

The header file <libmdsserver/macros.h> contains macros for readability and code reduction, it also contains macros and definitions for portability; they may either provide portability by nature, or provide one place to do modifications to port the system.

xasprintf [(char* buffer, ...) -> int]
     This is a wrapper for asprintf that has two important properties, the buffer is guaranteed to be NULL on failure, and it will return zero on and only on success. Unlike asprintf, xasprintf takes the buffer's variable as its first argument rather than the address of that variable.

xsnprintf [(char buffer[], ...) -> int]
     This is a wrapper for snprintf that allows you to forget about the buffer size. When you know how long a string can be, you should use sprintf. But when you cannot know for sure you should use xsnprintf. xsnprintf works exactly as sprintf, but it will require that the first argument is defined using [] rather than * because it will use this to find out how large the buffer is so it can call snprintf with that size.

eprint [(const char* format) -> int]
     A wrapper for fprintf that prints a string prefixed with the value of *argv to stderr. This wrapper also as a line feed to the end of the text. Because eprintf naïvely wraps fprintf, all `%':s in the string must be duplicated.

eprintf [(const char* format, ...) -> int]
     eprint extends eprint with variadic arguments that can be used to insert values into the format string just like you can do in fprintf.

iprint [(const char* format) -> int]
     A wrapper for fprintf that prints a string prefixed with the value of *argv, as well a label telling the user that the output is part of a state and statistics dump, to stderr. This wrapper also as a line feed to the end of the text. Because eprintf naïvely wraps fprintf, all `%':s in the string must be duplicated.

iprintf [(const char* format, ...) -> int]
     eprint extends iprint with variadic arguments that can be used to insert values into the format string just like you can do in fprintf.

with_mutex [(pthread_mutex_t mutex, instructions)]
     Wraps instructions with errno = pthread_mutex_lock(mutex); and errno = pthread_mutex_unlock(mutex);, so a set of instructions can be invoked inside mutex protection.

with_mutex_if [(pthread_mutex_t mutex, condition, instructions)]
     An alternative to with_mutex where instructions is wrapped around if (condition) which in turn is wrapped inside the mutex protection.

max [(a, b)]
     Returns the higher value of a and b.

min [(a, b)]
     Returns the lower value of a and b.

buf_cast [(char* buffer, type, size_t index)]
     Casts buffer to a type buffer and subscripts to the index:th element. You can either use this function as a getter or a setter.

buf_set [(char* buffer, type, size_t index, type variable) -> type]
     Wrapper for buf_cast that sets the addressed element to the value of variable.

buf_get [(const char* buffer, type, size_t index, type variable) -> type]
     Wrapper for buf_cast that sets the value of variable to the value of the addressed element.

buf_next [(char* buffer, type, size_t count) -> char*]
     Increases the pointer buffer by the size of type count types.

buf_prev [(char* buffer, type, size_t count) -> char*]
     Decreases the pointer buffer by the size of type count types.

buf_set_next [(char* buffer, type, type variable) -> type]

          buf_set(buffer, type, 0, variable),
          buf_next(buffer, type, 1);

buf_get_next [(char* buffer, type, type variable) -> type]

          buf_get(buffer, type, 0, variable),
          buf_next(buffer, type, 1);

strequals [(const char* a, const char* b) -> int]
     Evaluates whether the strings a and b are equals, neither may be NULL.

startswith [(const char* haystack, const char* needle) -> int]
     Evaluates whether the string haystack starts with the string needle, neither may be NULL.

drop_privileges [(void) -> int]
     Sets the effective user to the real user and the effective group to the real group. This is used by most servers and ensure that they are not running with unnecessary privileges. Returns zero on and only on success.

monotone [(struct timespec* time_slot) -> int]
     Stores the time of an unspecified monotonic clock into time_slot. Returns zero on and only on success.

xclose [(int fd) -> void]
     Wrapper for the close function. This wrapper will retry if the call is interrupted by a signal. It will however not return value, but you can detect if an error have occured by inspecting errno, it is guaranteed to be zero on success and otherwise indicate the error that occurred.

xfclose [(FILE* f) -> void]
     Wrapper for the fclose function. This wrapper will retry if the call is interrupted by a signal. It will however not return value, but you can detect if an error have occured by inspecting errno, it is guaranteed to be zero on success and otherwise indicate the error that occurred.

close_files [(condition) -> void]
     Closes all file descriptors named by a variable fd for which condition evalutes to non-zero.

xfree [(void** array, size_t elements) -> void]
     Calls free on the first elements elements in array, and than calls free on array. This macro requires size_t i is declared.

xmalloc [(type* var, size_t elements, type) -> int]
     Allocates a type* with elements elements and stores the allocated pointer to var. Returns zero on and only on success.

xbmalloc [(type* var, size_t bytes) -> int]
     Allocates bytes bytes and stores the allocated pointer to var. Returns zero on and only on success.

xcalloc [(type* var, size_t elements, type) -> int]
     Allocates a zero-initialised type* with elements elements and stores the allocated pointer to var. Returns zero on and only on success.

xbcalloc [(type* var, size_t bytes) -> int]
     Allocates and zero-initialises bytes bytes and stores the allocated pointer to var. Returns zero on and only on success.

xrealloc [(type* var, size_t elements, type) -> int]
     Reallocates var and updates the variable var accordingly. var will be allocated to have elements elements of the type type. If var is NULL a new allocation is created. If elements is zero, var will be deallocated. Returns zero on and only on success. On failure, var will be NULL, so you must store the var into another variable in case this macro fails.

xxrealloc [(type* old, type* var, size_t elements, type) -> int]
     Variant of xrealloc that will return with old set to NULL on success, and old set to var on error. Like xrealloc, xxrealloc returns zero on and only on success.

yrealloc [(type* tmp, type* var, size_t elements, type) -> int]
     Variant of xrealloc that will store var to tmp before reallocating var and then restore var if the reallocation failed. Like xrealloc, yrealloc returns zero on and only on success.

growalloc [(type* old, type* var, size_t elements, type) -> int]
     When using this macro var should be a type* pointer allocated for elements elements of the type type. This macro will reallocate var to contain twice as many elements and update elements accordingly. On failure nothing changes. You must specify a auxiliary type* variable and specify it in as the old parameter. Returns zero on and only on success.

xstrdup [(char* var, const char* original) -> int]
     Wrapper for strdup that returns zero on and only on success. original is duplicate and the duplicate is stored in the variable var. If original is NULL, var is set to NULL and zero is returned.

xmemdup [(void* var, const void* original, size_t elements, type) -> int]
     Allocates a pointer of the type type* with room for elements elements and stores the pointer to var. If successful, the content of original (elements elements of size sizeof(type*)) is copied to var, and zero is returned. On failure, a non-zero value is returned.

xperror [(const char* str) -> void]
     Invokes perror(str) if and only if errno is non-zero and then sets errno to zero. str should unless you have a specific reason be *argv.

fail_if [(condition) -> void]
     If condition is satisfied, a jump is made to the label fail. Additionally the location of failure will be printed to standard error.

exit_if [(condition, instructions) -> void]
     If condition is satisfied, instructions is invoked and 1 is return:ed.

Additionally, <libmdsserver/macros.h> defines any missing signal name: currently SIGDANGER, SIGINFO and SIGUPDATE, and by inclusion of <libmdsserver/macro-bits.h>, variants of atoi for portability and convenience:

atoz
     Parse a human readable const char* 10-radix integer to a size_t.

atosz
     Parse a human readable const char* 10-radix integer to a ssize_t.

atoh
     Parse a human readable const char* 10-radix integer to a short int.

atouh
     Parse a human readable const char* 10-radix integer to an unsigned short int.

atou
     Parse a human readable const char* 10-radix integer to an unsigned int.

atoul
     Parse a human readable const char* 10-radix integer to an unsigned long int.

atoull
     Parse a human readable const char* 10-radix integer to an unsigned long long int.

ato8
     Parse a human readable const char* 10-radix integer to an int8_t.

atou8
     Parse a human readable const char* 10-radix integer to an uint8_t.

ato16
     Parse a human readable const char* 10-radix integer to an int16_t.

atou16
     Parse a human readable const char* 10-radix integer to an uint16_t.

ato32
     Parse a human readable const char* 10-radix integer to an int32_t.

atou32
     Parse a human readable const char* 10-radix integer to an uint32_t.

ato64
     Parse a human readable const char* 10-radix integer to an int64_t.

atou64
     Parse a human readable const char* 10-radix integer to an uint64_t.

atoj
     Parse a human readable const char* 10-radix integer to an intmax_t.

atouj
     Parse a human readable const char* 10-radix integer to an uintmax_t.

The header file <libmdsserver/macros.h>, also define the macro TEMP_FAILURE_RETRY if missing, however without a return value but will clear errno if no error occurs (glibc will not clear errno on success, however this behaviour is defined MDS_LIBMDSSERVER_MACROS_DEFINED_TEMP_FAILURE_RETRY will be defined.), and creates the alias CLOCK_MONOTONIC_RAW for CLOCK_MONOTONIC unless CLOCK_MONOTONIC_RAW is already defined.

Auxiliary Functions
===================

In the header file <libmdsserver/util.h>, libmdsserver defines common functions to help write servers more concisely.

parse_client_id [(const char* str) -> uint64_t]
     Convert a client ID string into a client ID integer.

getenv_nonempty [(const char* var) -> char*]
     Read an environment variable, return NULL if the variable's value is an empty string.

prepare_reexec [(void) -> int]
     Prepare the server so that it can re-execute into a newer version of the executed file.

     This is required for two reasons:

      1. We cannot use argv[0] as PATH-resolution may cause it to reexec into another pathname, and maybe to wrong program. Additionally argv[0] may not even refer to the program, and chdir could also hinter its use.

      2. The kernel appends  (deleted) to /proc/self/exe once it has been removed, so it cannot be replaced.

     Returns zero on success and -1 on error.

reexec_server [(int argc, char** argv, int reexeced) -> void]
     Re-execute the server. If prepare_reexec failed or has not been called, argv[0] will be used as a fallback. This functions has three input parameters:

     argc
          The number of elements in argv.

     argv
          The command line arguments.

     reexeced
          Whether the server has previously been re-executed.

     This function only returns on failure.

xsigaction [(int signo, void (*function)(int signo)) -> int]
     sigaction with the same parameters as signal. This function should only be used for common mds signals and signals that does not require any special settings. This function may choose to add additional behaviour depending on the signal, such as blocking other signals. Returns zero on success and -1 on error.

send_message [(int socket, const char* message, size_t length) -> size_t]
     Send the message messsage, of length length over the socket that is access with the file descriptor socket. Returns the number of bytes that have been sent, even on error.

strict_atoi [(const char* str, int* value, int min, int max) -> int]
     A version of atoi that is strict about the syntax and bounds. Parses the string str into an int and stores it in *value. If the string is not a 10-radix integer or has a value outside [min, max], -1 is returned, otherwise zero is returned.

strict_atou
     A variant of strict_atoi that uses unsigned int instead of int on its parameters.

strict_atoh
     A variant of strict_atoi that uses short int instead of int on its parameters. Note however that min and max is in int, because smaller types should not be passed as arguments.

strict_atouh
     A variant of strict_atoi that uses unsigned short int instead of int on its parameters. Note however that min and max is in unsigned int, because smaller types should not be passed as arguments.

strict_atol
     A variant of strict_atoi that uses long int instead of int on its parameters.

strict_atoul
     A variant of strict_atoi that uses unsigned long int instead of int on its parameters.

strict_atoll
     A variant of strict_atoi that uses long long int instead of int on its parameters.

strict_atoull
     A variant of strict_atoi that uses unsigned long long int instead of int on its parameters.

strict_atoj
     A variant of strict_atoi that uses intmax_t instead of int on its parameters.

strict_atouj
     A variant of strict_atoi that uses uintmax_t instead of int on its parameters.

strict_atoz
     A variant of strict_atoi that uses size_t instead of int on its parameters.

strict_atosz
     A variant of strict_atoi that uses ssize_t instead of int on its parameters.

strict_ato8
     A variant of strict_atoi that uses int8_t instead of int on its parameters. Note however that min and max is in int, because smaller types should not be passed as arguments.

strict_atou8
     A variant of strict_atoi that uses uint8_t instead of int on its parameters. Note however that min and max is in int, because smaller types should not be passed as arguments.

strict_ato16
     A variant of strict_atoi that uses int16_t instead of int on its parameters. Note however that min and max is in int, because smaller types should not be passed as arguments.

strict_atou16
     A variant of strict_atoi that uses uint16_t instead of int on its parameters. Note however that min and max is in unsigned int, because smaller types should not be passed as arguments.

strict_ato32
     A variant of strict_atoi that uses int32_t instead of int on its parameters.

strict_atou32
     A variant of strict_atoi that uses uint32_t instead of int on its parameters.

strict_ato64
     A variant of strict_atoi that uses int64_t instead of int on its parameters.

strict_atou64
     A variant of strict_atoi that uses uint64_t instead of int on its parameters.

full_write [(int fd, const char* buffer, size_t length) -> int]
     Send the buffer buffer, with the length length, into the file whose file descriptor is fd and ignores interruptions. Returns zero on success and -1 on error.

full_read [(int fd, size_t* length) -> char*]
     Read the file whose file descriptor is fd completely and ignore interruptions. If length if not NULL, the length of the read file is stored in *length. On success, the read content is retured, on error NULL is returned.

full_send [(int socket, const char* message, size_t length) -> int]
     Send the message message, with the length length, to the socket whose file descriptor is socket and ignores interruptions. Returns zero on success and -1 on error.

startswith_n [(const char*, const char*, size_t, size_t) -> int]
     Check whether a string begins with a specific string, where neither of the strings are necessarily NUL-terminated. The parameters are:

     const char* haystack
          The string that should start with the other string.

     const char* needle
          The string the first string should start with.

     size_t haystack_n
          The length of haystack.

     size_t needle_n
          The length of needle.

     Returns 1 if haystack beings with needle, otherwise zero is returned.

uninterruptable_waitpid [(pid_t pid, int* restrict status, int options) -> pid_t]
     Wrapper around waitpid that never returns on an interruption unless it is interrupted one hundred times within the same clock second. The parameters and return value are exactly those of waitpid.

verify_utf8[(const char* string, int allow_modified_nul) -> int]
     Checks whether a NUL-terminated string's encoding matches UTF-8. This function will reject the string if it does not use the shorted possible byte-combination for each character. However, if allow_modified_nul is set, it will allow 192 128 in place of 0 for a NUL-character. (Remember 0 is used to terminated the string, but 192 128 is not.) This function returns zero if the string is properly formatted, and -1 otherwise.

Data Structures
===============

libmdsserver provides a small set of data structures that are used by the mds servers. All of these are written with marshal-functionallity.

client_list_t {also known as struct client_list}
     In the header file <libmdsserver/client-list.h>, libmdsserver defines a dynamic list for storing client ID:s.

linked_list_t {also known as struct linked_list}
     In the header file <libmdsserver/linked-list.h>, libmdsserver defines a linear array sentinel doubly linked list.

hash_table_t {also known as struct hash_table}
     In the header file <libmdsserver/hash-table.h>, libmdsserver defines a hash table.

fd_table_t {also known as struct fd_table}
     In the header file <libmdsserver/fd-table.h>, libmdsserver defines a lookup table for small positive integer keys, intended as an alternative to hash tables for file descriptors as keys.

mds_message_t {also known as struct mds_message}
     In the header file <libmdsserver/mds-message.h>, libmdsserver defines a data structure for message between the server or client and the master server, with the capability of reading for a socket.

hash_list {abstract}
     In the header file <libmdsserver/hash-list.h>, libmdsserver defines an abstract class known as hash list. It is intended as an alternative to hash tables, where the number of stored elements is low.

These data structures share a common set of associated methods. However, they do not use the same methods; they are identical except they are are named with the associated data structure. We will use X_t as an example.

X_destroy [(X_t* restrict this) -> void]
     Releases all resouces in *this, this itself is however not free:d.

     However, hash_table_destory and fd_table_destory have another signature.

X_clone [(const X_t* restrict this, X_t* restrict out) -> int]
     Create a deep duplicate of *this and store it in *out.

X_marshal_size [(const X_t* restrict this) -> size_t]
     Calculates the exact allocate size needed for the parameter data in the method X_marshal if called with the same this parameter.

X_marshal [(const X_t* restrict this, char* restrict data) -> void]
     Marshal the state of *this into data. The number of bytes that will be stored (contiguously) in data can be calculated with X_marshal_size.

X_unmarshal [(X_t* restrict this, char* restrict data)) -> int]
     Unmarshal a X_t from data into *this. Returns zero on success and -1 on error. The number of bytes read from data should, if required, have been precalculated with X_marshal_size and stored in an earlier location of data.

     However, hash_table_unmarshal and fd_table_unmarshal have another signature.

Client List
-----------

To create a client list, allocate a client_list_t* or otherwise obtain a client_list_t*, and call client_list_create with that pointer as the first argument, and the 0 as the second argument, unless you want to tune the initialisation. client_list_create will return zero on and only on successful initialisation. client_list_create's second parameter --- size_t capacity --- can be used to specify how many element the list should initially fit. It will grow when needed, but it is a good idea to tell it how many elements you are planning to populate it with.

client_list_t has two associated methods for manipulating its content:

client_list_add [(client_list_t* restrict this, uint64_t client) -> int]
     This method will add the element client to the list *this, and return zero on and only on success.

client_list_remove [(client_list_t* restrict this, uint64_t client) -> void]
     This method will remove exactly one occurrence, provided that there is at least one occurrence, of the element client for the list *this.

To retrieve the number elements stored in a list, reads its variable size_t size. The variable uint64_t* clients is used to retrieve stored elements.

     void print_elements(client_list_t* this)
     {
       size_t i;
       for (i = 0; i < this->size; i++)
         printf("Element #%zu: %" PRIu64 "\n", i, this->elements[i]);
     }

Linked List
-----------

linked_list_t is a linear array sentinel doubly linked list. This means that is implemented using arrays rather than node references. More specifically, since it is doubly linked (And not using XOR-linking.), it is implemented using three arrays:

values [size_t*]
     The value stored in each node.

next [ssize_t*]
     The next node for each node, edge if the current node is the last node, and LINKED_LIST_UNUSED if there is no node on this position.

previous [ssize_t*]
     The previous node for each node, edge if the current node is the first node, and LINKED_LIST_UNUSED if there is no node on this position.

The linked list has a sentinel node that joins boths ends of the list. The index of this node is stored in the variable edge.

Because the list is implemented using arrays, if the number of elements in it shinks considerably, it will not be able to automatically free unused space. Instead you must call linked_list_pack:

linked_list_pack [(linked_list_t* restrict this) -> int]
     Pack the list so that there are no reusable positions, and reduce the capacity to the smallest capacity that can be used. Note that values (nodes) returned by the list's methods will become invalid. Additionally (to reduce the complexity) the list will be defragment so that the nodes' indices are continuous. This method has linear time complexity and linear memory complexity.

To create a linked list list, allocate a linked_list_t* or otherwise obtain a linked_list_t*, and call linked_list_create with that pointer as the first argument, and the 0 as the second argument, unless you want to tune the initialisation. linked_list_create will return zero on and only on successful initialisation. linked_list_create's second parameter --- size_t capacity --- can be used to specify how many element the list should initially fit. It will grow when needed, but it is a good idea to tell it how many elements you are planning to populate it with.

There are five methods adding and removing items to and from a linked list:

linked_list_insert_after [(this, size_t value, ssize_t predecessor) -> ssize_t]
     Create a new node with the value value and add it to the list *this after the node predecessor. On success, the new node is returned, on failure LINKED_LIST_UNUSED is returned.

linked_list_insert_before [(this, size_t value, ssize_t successor) -> ssize_t]
     Create a new node with the value value and add it to the list *this before the node successor. On success, the new node is returned, on failure LINKED_LIST_UNUSED is returned.

linked_list_remove_after [(this, ssize_t predecessor) -> ssize_t]
     Remove and return the node in the list *this directly after the node predecessor.

linked_list_remove_before [(this, ssize_t successor) -> ssize_t]
     Remove and return the node in the list *this directly before the node predecessor.

linked_list_remove [(this, ssize_t node) -> void]
     Remove the node node from the list *this.

The data type for this is linked_list_t* with the restrict modifier for these and all other linked_list_t methods.

Note that if the node this->edge is removed, the list become circularly linked and the sentinel will become missing which renders invokation of all macros undefined in behaviour. Further note that removing the sentinel while it is the only node in the list invokes undefined behaviour. Also note that addressing non-existing nodes invokes undefined behaviour.

<libmdsserver/linked_list.h> defines two macros for inserting nodes at the edges of a linked list and two macros for removing nodes from the edges of a linked list:

linked_list_insert_beginning [(linked_list_t* this, size_t value) -> ssize_t]
     Create a new node with the value value in insert it to the beginning of the list *this. On success, the new node is returned, on failure LINKED_LIST_UNUSED is returned.

linked_list_insert_end [(linked_list_t* this, size_t value) -> ssize_t]
     Create a new node with the value value in insert it to the end of the list *this. On success, the new node is returned, on failure LINKED_LIST_UNUSED is returned.

linked_list_remove_beginning [(linked_list_t* this) -> ssize_t]
     Remove and return the first node in the list *this.

linked_list_remove_end [(linked_list_t* this) -> ssize_t]
     Remove and return the node node in the list *this.

Additionally the library defines a macro that wrappes the for-keyword to iterate over all nodes (except the sentinel node) the a linked list:

foreach_linked_list_node [(linked_list_t this, ssize_t node)]
     Wrapper for for-keyword that iterates over each element in the list this, and store the current node to the variable named by the parameter node for each iterations.

          void print_linked_list_values(linked_list_t* list)
          {
            ssize_t node;
            foreach_linked_list_node (*list, node)
              printf("%zi\n", list->values[node]);
          }

     Note that the data type for this in the macro is not a pointer.

There is also a method intended for debugging:

linked_list_dump [(linked_list_t* restrict this, FILE* restrict output) -> void]
     The all internal data of the list *this into the stream output.

Tables
------

libmdsserver defines two similar data structures: fd_table_t and hash_table_t. Whenever a method exists for both data structures we will write X_table instead of fd_table and hash_table. Additionally, unless otherwise stated, a method's parameter named this will be of the type hash_table_t* if the method's name start with hash_table and fd_table_t* if the method's name start with fd_table, with the restrict modifier.

X_table_create [(this) -> int]
     Initialises *this so it can be used as a table. Returns zero on and only on success.

     These methods are defined as macros.

X_table_create_tuned [(this, size_t initial_capacity) -> int]
     Initialises *this so it can be used as a table, and makes its initial capacity at least initial_capacity. Returns zero on and only on success.

     hash_table_create_tuned is defined as a macro.

hash_table_create_fine_tuned [(this, size_t initial_capacity, float load_factor) -> int]
     Initialises *this so it can be used as a table, and makes its initial capacity at least initial_capacity and its load factor load_factor. Returns zero on and only on success.

X_table_destroy [(this, free_func* key_freer, free_func* value_freer) -> void]
     Release all resources in the table *this, but do not free this itself. Should be called even if construction fails. If keys_freer is not NULL, this method will be called for each key. If values_freer is not NULL, this method will be called for each value.

X_table_contains_value [(const this, size_t value) -> int]
     Check whether the value value is stored in the table *this.

X_table_contains_key [(const this, key) -> int]
     Check whether the key code is used in the table *this.

     The data type for the parameter key is size_t for hash_table and int for fd_table.

X_table_get [(const this, key) -> size_t]
     Look up a value by its key key in the table *this. Zero will be returned if the key was not used.

hash_table_get_entry [(const this, size_t key) -> hash_entry_t*]
     Look up an entry by its key key in the table *this. NULL will be returned if the key was not used.

X_table_put [(this, key, size_t value) -> size_t]
     Map the value value to the key key in the talbe *this. If a value was already mapped to the key, that value will be returned, otherwise zero will be returned. Zero will also be returned on error. errno will be set to zero on and only on success.

     The data type for the parameter key is size_t for hash_table and int for fd_table.

X_table_remove [(this, key) -> size_t]
     Unmaps the key key for the table *this. If a value was mapped to the key, that value will be returned, otherwise zero will be returned.

     The data type for the parameter key is size_t for hash_table and int for fd_table.

X_table_clear [(this) -> void]
     Unmaps all keys in the table *this.

X_table_unmarshal [(this, char* restrict data, remap_func* remapper) -> int]
     As described in Data Structures but with one additional parameter: remapper. If this parameter is not NULL this method is used to edit values. It will be called once for each value and the output of the method will be used inplace of the input value.

<libmdsserver/hash-table.h> also defines as wrapper macro for the for-keyword:

foreach_hash_table_entry [(hash_table_t this, size_t i, hash_entry_t* entry)]
     Iterates over entry element in the hash table this. On each iteration, the entry will be stored to the variable entry and the bucket index will be stored to the variable i.

          void print_hash_table(hash_table_t* table)
          {
            hash_entry_t* entry;
            size_t i;
            foreach_hash_table_entry (*table, i, entry)
              printf("%zu --> %zu\n", entry->key, entry->value);
          }

     Note that the data type for the parameter this is not a pointer.

The structures hash_table_t and fd_table_t contain the variable value_comparator which by default is NULL. If this variable is set to NULL, two values will be considered equal if and only if they are numerically identical; otherwise two values will be considered equal if and only if value_comparator returned a non-zero value if those two values are used for the method's arguments. The data type for value_comparator is compare_func*.

hash_table_t also contains two other variables:

key_comparator [compare_func*]
     Identical to value_comparator, except it is used for keys rather the values.

hasher [hash_func*]
     By default, the hash value for key is identical to the key itself. However, if this variable is not NULL, it will be used to calculate the hash value for keys.

There is a secondary data structure defined for hash tables: hash_entry_t {also known as struct hash_entry}. It is the data structure used for entries in a hash table. hash_entry_t contain three variables you may be interested in:

key [size_t]
     The key.

value [size_t]
     The value associated with the key.

hash [size_t]
     The hash value of the key.

By inclusion of <libmdsserver/table-common.h>, <libmdsserver/hash-table.h> and <libmdsserver/fd-table.h> defines four typedef:s for method signatures:

compare_func [(size_t a, size_t b) -> int]
     A method that performs a comparison of two objects. Should return non-zero if and only if a and b are to be considered equal in the given context.

hash_func [(size_t value) -> size_t]
     A method that hashes an object or a value. Should return the hash value for value.

free_func [(size_t obj) -> void]
     A method that, to the extent that is appropriate, releases the object obj's resources and free:s it.

remap_func [(size_t obj) -> size_t]
     A method that translates a object into a new object. The method should return new object that should replace the object obj.

If you are working with strings, you may consider including the header file <libmdsserver/hash-help.h>. It defines to useful methods:

string_hash [(const char* str) -> size_t]
     Calculate and returns the hash value of the string str.

string_comparator [(char* str_a, char* str_b) -> int]
     Returns non-zero if either both str_a and str_b are NULL or neither are NULL but are identical strings by content upto their first NUL characters (or by address.)

These methods are defined as pure and static inline.

Hash List
---------

hash_list is an abstract data structure, provided as an alternative to hash tables with a low number of elements. hash_list is a associated dynamic list, with hash keys, that keeps removed slot free for reuse until they are as many as the occupied slots.

To use hash_list, a concrete subclass of it must be created. To do this, call the macro CREATE_HASH_LIST_SUBCLASS. It takes four parameters:

 1. The name of the subclass, this must not be a string, but rather formated as an identifier. This text will replace the hash_list in all that the macro defines.

 2. The data type of the keys. We will hence refer to this as KEY_T.

 3. A const version of the data type of the keys. We will hence refer to this as const KEY_T.

 4. The data type of the values. We will hence refer to this as VALUE_T. It is however internally type-defined as hash_list_value_t, but this is not guaranteed to be true in the future.

CREATE_HASH_LIST_SUBCLASS will define two structures, two method type definitions, four static inline methods for the creator of the subclass to implement, and a set of methods, as well as one auxiliary type definition (This type definition would be hash_list_value_t as specified above.).

The first structure is called hash_list_entry_t {also known as struct hash_list_entry}. Keep in mind that hash_list is replaced by the first argument in the call to CREATE_HASH_LIST_SUBCLASS. This structure represents a entry, or slot, the hash list, it contains three elements:

key [KEY_T]
     The key of the entry. Will be NULL if the slot is unused; a NULL on a key is disallowed. Note that NULL is equivalent to zero if the data type is numeral primitively.

key_hash [size_t]
     The hash of the key. This element is transparent to the user of the class.

value [VALUE_T]
     The value.

The other structure is called hash_list_t {also known as struct hash_list}. This structure represents the entire hash list. It contains six elements:

allocated [size_t]
     The number of allocated slots. This element is transparent to the user of the class.

unused [size_t]
     The number of unused slot that has previously be used. This element is transparent to the user of the class.

used [size_t]
     The number of slots that have been used, even if no longer used. This element is transparent to the user of the class.

slots [hash_list_entry_t*]
     The allocation for the slots. This element is transparent to the user of the class.

freer [hash_list_entry_free_func*]
     Method used to free keys and values of entries. If left NULL, no keys or values are freed. This value must be set after hash_list_create or hash_list_unmarshal is called, not before.

hasher [hash_list_key_hash_func*]
     method used to calculate the hash of a key. If left NULL, the identity hash is used, that is, the address of the key, or if it is numeral, it is casted to size_t. This value must be set after hash_list_create or hash_list_unmarshal is called, not before.

The two method-type definitions are:

hash_list_entry_free_func [(hash_list_entry_t* entry) -> void]
     The method shall free the key and value, if defined in such a way that they can be freed. It is guaranteed that neither entry or entry->key are NULL.

hash_list_key_hash_func [(const KEY_T key) -> size_t]
     The method shall return the hash of the key. It is guaranteed that key is not NULL.

There are five methods specific to hash_list_t. The this-parameter's data type for this methods are hash_list_t* with the restrict modifier.

hash_list_create [(this, size_t capacity) -> int]
     Create a hash list, and store it in this. The hash list's initial capacity will be at least the value capacity. If, however, capacity is zero, a default capacity will be used. Zero is returned on success, -1 is returned on error.

hash_list_pack [(this) -> int]
     Pack the list so that there are no reusable positions, and reduce the capacity to the smallest capacity that can be used. This method has linear time complexity and constant memory complexity. Zero is returned on success, -1 is returned on error. Errors are however non-fatal and can be ignored, it only means that the capacity could not be reduces, because a called to realloc failed.

hash_list_get [(const this, const KEY_T key, VALUE_T* restrict value) -> int]
     Look up a value, with the key key, in the hash list this. The found value will be stored in *value. This method cannot fail, therefore it cannot return a value indicating that it failed. Instead it returns one if the entry was found and nought if it was not found.

hash_list_put [(this, KEY_T key, const VALUE_T* restrict value) -> int]
     Store the value stored in *value to the hash list this. The value will be stored with the key key. If a value with this key already exists, that entry will be freed and replaced. key will be stored in the hash list, and the caller is not longer responsble for freeing it unless the call to this function fails. Zero is returned on success, -1 is returned on error.

     If however value is NULL, the entry with the key key will be removed if it exists. And zero is always returned. The caller will be responsible for freeing key in this case.

hash_list_remove [(this, const KEY_T key) -> void]
     Calling this function is equivalent to calling hash_list_put with the last argument being NULL. However, it allows the key to be stored with const and it does not have a return value.

Keep in mind that the methods

  * hash_list_destroy

  * hash_list_clone

  * hash_list_marshal_size

  * hash_list_marshal

  * hash_list_unmarshal

also have hash_list exchanged with whatever is in the first argument of the on the call to CREATE_HASH_LIST_SUBCLASS. Additionally hash_list_clone cannot clone keys or values that are pointers. So if freeing method is set, you need to manually clone keys and values after calling hash_list_clone.

CREATE_HASH_LIST_SUBCLASS also defines the prototypes for four functions the user of the class is required to implement. This four functions are defined with static inline. The entry parameter is defined with the type hash_list_entry_t* (Keep in mind that hash_list is replaced with the value of the first argument in CREATE_HASH_LIST_SUBCLASS).

hash_list_key_comparer [(const KEY_T key_a, const KEY_T key_b) -> int]
     Compare two keys, key_a and key_b. The function shall return zero on inequality and non-zero on equality.

hash_list_submarshal_size [(const entry) -> size_t]
     The function shall return the number of bytes required to marshal entry->key and entry->value.

hash_list_submarshal [(const entry, char* restrict data) -> size_t]
     The function shall marshal entry->key and entry->value into the buffer data. The function shall then return the number of written bytes, that is, the value returned by hash_list_submarshal_size.

hash_list_subunmarshal [(entry, char* restrict data) -> size_t]
     The function shall unmarshal the key and value of an entry stored in the beginning of data. The unmarshaled key and value should be stored to entry->key and entry->value, respectively. The function shall then return the number of read bytes, that is, the value hash_list_submarshal_size returned when the marshal took place, or equivalently, the will it would return after the unmarshalling. The function shall return zero on error.

<libmdsserver/hash-list.h> also defines a macro that is uneffected by CREATE_HASH_LIST_SUBCLASS.

foreach_hash_list_entry [(hash_list_t this, size_t i, hash_list_entry_t* entry)]
     This marcro is a warpper for the for-keyword. It iterates over entry element in the hash list this. On each iteration, the entry (used slots) will be stored to the variable entry. The variable i defined as a size_t must be available for the macro to use freely.

          void print_hash_list(hash_list_t* table)
          {
            hash_list_entry_t* entry;
            size_t i;
            foreach_hash_table_entry (*table, i, entry)
              printf("%zu --> %zu\n", entry->key, entry->value);
          }

     Note thay the data type for the parameter this is not a pointer.

Message Structure
-----------------

Apart from internal data mds_message_t contains four variables:

headers [char**]
     The headers in the message, each element in this list as an unparsed header, it consists of both the header name and its associated value, joined by `: '. A header cannot be NULL (unless its memory allocation failed,) but headers itself is NULL if there are no headers. The Length-header should be included in this list.

header_count [size_t]
     The number of headers in the message.

payload [char*]
     The payload of the message, NULL if none (of zero-length).

payload_size [size_t]
     The length of the message's payload. This value will be the same as the value of the Length-header.

There are six methods specific to mds_message_t. The this-parameter's data type for this methods are mds_message_t* with the restrict modifier.

mds_message_initialise [(this) -> int]
     Initialises *this so that it can be used by mds_message_read. Returns zero on and only on success. On failure you should destroy *this using mds_message_destroy.

mds_message_zero_initialise [(this) -> void]
     This method is similar to mds_message_initialise, however it cannot fail and thus have no return value. The difference it is action is that it will not allocate an internal buffer.

mds_message_extend_headers [(this, size_t extent) -> int]
     Ensures that extent additional headers can be stored in the *this. Returns zero on and only on success.

mds_message_read [(this, int fd) -> int]
     Reads the next message from the socket file descriptor fd and stores it in *this. Returns zero on success and non-zero on error or interruption. *this should be destroyed using mds_message_destroy on error but not on interruption. If -2 is returned errno will not have been set; -2 indicates that the message is malformated, which is a state that cannot be recovered from.

mds_message_compose_size [(const this) -> size_t]
     This method is to mds_message_compose as mds_message_marshal_size is to mds_message_marshal.

mds_message_compose [(const this, char* restrict data) -> void]
     This method is similar to mds_message_marshal. The only difference is that it will not store internal data and instead create a message that can be broadcasted in the display server message passing system.

mds-base.o
**********

mds-base.c and mds-base.h as an object filepair whose purpose is similar to libmdsserver. mds-base is compiled into all mds servers and implements common procedures including main. It also complements procedures that are weakly defined, that is, if the server implementation also defines them, the server implementations procedure replaces mds-base's implementation at compile-time.

mds-base defines one function that you can call from threads you create and functions that should be implement depending on specified conditions:

trap_signals [(void) -> int]
     Set up signal traps for all especially handled signals. Returns zero on and only on success.

mds-base weakly defines functions that you can replace if they do not suit your needs:

parse_cmdline [(void) -> int]
     Parses command line arguments. Returns zero on and only on success.

     This function will parse the following options:

     --initial-spawn
          It is the first time the server is spawn by its spawner process.

     --respawn
          The server was respawned.

     --re-exec
          The server is re-executing.

     --alarm=SECONDS
          Kill the process after SECONDS seconds. At most one minute.

     --on-init-fork
          Fork the process to detach it from its parent when the server has been initialised.

     --on-init-sh=COMMAND
          When the server has been initialised, run the command COMMAND.

     --immortal
          The server should do its best not to die. For example do not die if SIGDANGER is received even if that is the server's default action.

connect_to_display [(void) -> int]
     Connects to the display. Returns zero on and only on success.

server_initialised [(void) -> int]
     This function should be called when the server has been properly initialised but before initialisation of anything that is removed at forking is initialised. Returns zero on and only on success.

signal_all [(int signo) -> void]
     This function should be implemented by the actual server implementation if the server is multi-threaded. It sends the singal signo to all threads except the current thread.

received_danger [(int signo) -> void]
     This function is called when a signal that signals the system is running out of memory has been received. The exact received signal is specified by the parameter signo. When this function is invoked, the server should free up all memory it can spare. When this function is invoked, it should set the variable danger to a non-zero value. If server_characteristics.danger_is_deadly is set, this function will never be called.

received_reexec [(int signo) -> void]
     This function is called when a signal that signals the server to re-execute has been received. The exact received signal is specified by the parameter signo. When this function is invoked, it should set the variables reexecing and terminating to a non-zero value.

received_terminate [(int signo) -> void]
     This function is called when a signal that signals the server to terminate has been received. The exact received signal is specified by the parameter signo. When this function is invoked, it should set the variable terminating to a non-zero value.

received_info [(int signo) -> void]
     This function is called when a signal that signals the server to dump state information and statistics has been received. The exact received signal is specified by the parameter signo.

fork_cleanup [(int status) -> void]
     This function should be implemented by the actual server implementation if the server has set server_characteristics.fork_for_safety to be a non-zero value. This function is called by the parent server process when the child server process exits, if the server has completed its initialisation. The parameter status specifies the child process exit status as returned by waitpid.

Additionally, mds-base expects the server implementation to define and implement a set of functions:

preinitialise_server [(void) -> int]
     This function will be invoked before initialise_server (if not re-executing) or before unmarshal_server (if not re-executing). Returns zero on and only on success.

initialise_server [(void) -> int]
     This function should initialise the server. It not invoked after a re-execution. Returns zero on and only on success.

postinitialise_server [(void) -> int]
     This function will be invoked after initialise_server (if not re-executing) or after unmarshal_server (if re-executing). Returns zero on and only on success.

marshal_server_size [(void) -> size_t, pure]
     Calculate and returns the number of bytes that will be stored by marshal_server. On failure the server should call abort or exit with failure status by other means. However it should not be possible for this function to fail. marshal_server_size must be pure (That is, define with and conforming to __attribute__((pure)).).

marshal_server [(char* state_buf) -> int]
     Marshal server implementation specific data into the buffer state_buf. Returns zero on and only on success.

unmarshal_server [(char* state_buf) -> int]
     Unmarshal server implementation specific data from the buffer state_buf and update the servers state accordingly. Returns zero on and only on success.

     On critical failure the program should call abort or exit with failure status by other means. That is, do not let reexec_failure_recover run successfully, if it unrecoverable error has occurred or one severe enough that it is better to simply respawn.

reexec_failure_recover [(void) -> int]
     Attempt to recover from a re-execution failure that has been detected after the server successfully updated it execution image. Returns zero on and only on success.

master_loop [(void) -> int]
     Perform the server's mission. Returns zero on and only on success.

mds-base also defines a number of global variables.

argc [int]
     Number of elements in argv.

argv [char**]
     Command line arguments.

is_respawn [int]
     Whether the server has been respawn rather than this being the initial spawn. This will be at least as true as is_reexec.

is_reexec [int]
     Whether the server is continuing from a self-reexecution.

is_immortal [int]
     Whether the server should do its best to resist event triggered death.

on_init_fork [int]
     Whether to fork the process when the server has been properly initialised.

on_init_sh [char*]
     Command the run (NULL for none) when the server has been properly initialised.

master_thread [pthread_t]
     The thread that runs the master loop.

terminating [volatile sig_atomic_t]
     Whether the server has been signaled to terminate.

reexecing [volatile sig_atomic_t]
     Whether the server has been signaled to re-execute.

danger [volatile sig_atomic_t]
     Whether the server has been signaled to free unneeded memory.

socket_fd [int]
     The file descriptor of the socket that is connected to the server.

mds-base expects the server implementation to define a variable that specifies how mds-base should behave:

server_characteristics [server_characteristics_t]
     This variable should declared by the actual server implementation. It must be configured before main is invoked. That is, it should be configured by a constructor. If it is configured at its definition, it is configured by a constructor; that is normally how you want to configured it.

server_characteristics_t {also known as struct server_characteristics} is a packed (That is, define with __attribute__((packed)).) with the following fields:

require_privileges [unsigned : 1]
     Setting this to zero will cause the server to drop privileges as a security precaution.

require_display [unsigned : 1]
     Setting this to non-zero will cause the server to connect to the display.

require_respawn_info [unsigned : 1]
     Setting this to non-zero will cause the server to refuse to start unless either --initial-spawn or --respawn is used.

sanity_check_argc [unsigned : 1]
     Setting this to non-zero will cause the server to refuse to start if there are too many command line arguments.

fork_for_safety [unsigned : 1]
     Setting this to non-zero will cause the server to place itself in a fork of itself when initialised. This can be used to let the server clean up fatal stuff after itself if it crashes. When the child exits, no matter how it exits, the parent will call fork_cleanup and then die in the same manner as the child.

danger_is_deadly [unsigned : 1]
     Setting this to non-zero without setting a signal action for SIGDANGER will cause the server to die if SIGDANGER is received. It is safe to set both danger_is_deadly and fork_for_safety to non-zero, during the call of server_initialised the signal handler for SIGDANGER in the parent process will be set to SIG_IGN independently of the value of danger_is_deadly if fork_for_safety is set to non-zero.

     This setting will be treated as set to zero if --immortal is used.

Keyboard Codes
**************

Keyboard servers receive scancodes from keyboard drivers. A scancode can either be comprised of one byte or three bytes. In each byte, the most significant bit (assuming unsigned bytes) is ignore, however for it first byte in the scancode it signifies whether the key was released: it is set of the key is released, and not set if the key was pressed or is being held down.

A scancode is comprised of three bytes if the lower 7-bits of the first byte is are all cleared, and the highest bit in the two following bytes are set.

Ignoring the most significant bit in all bytes, the keycode is the value of the byte if the scancode is a single byte scancode. If the scancode is comprised of three bytes, the first byte is ignored and the keycode is a \cdot 128 + b where a is the value of the second byte and b is the value of the third byte.

105-keys Keycodes
=================

This is a list of keyboards for the 105-keys keyboards, using QWERTY-layout for reference.

1
     Escape key

2--11
     Keys: 1, 2, 3, 4, 5, 6, 7, 8, 9, 0

12
     Key right of 0.

13
     Key left of Backspace

14
     Backspace key

15
     Tab key

16--25
     Keys: q, w, e, r, t, y, u, i, o, p

26
     Key right of p, once removed

27
     Key right of p, twice removed

28
     Return key

29
     Left Control key

30--38
     Keys: a, s, d, f, g, h, j, k, l

39
     Key right of l, once removed

40
     Key right of l, twice removed

41
     Key left of 1

42
     Left Shift key

43
     Key right of l, three times removed

44--50
     Keys: z, x, c, v, b, n, m

51
     Key right of m, once removed

52
     Key right of m, twice removed

53
     Key right of m, three times removed

54
     Right Shift key

55
     Multiply key on the keypad

56
     Alternative key

57
     Space key

58
     Caps Lock key

59--68
     Keys: F1 through F10

69
     Num Lock key

70
     Scroll Lock key

71--73
     7, 8, 9 keys on the keypad

74
     Minus key on the keypad

75--77
     4, 5, 6 keys on the keypad

78
     Plus key on the keypad

79--82
     1, 2, 3, 0 keys on the keypad

83
     Comma key on the keypad

86
     Key left of z

87
     F11 key

88
     F12 key

96
     Return key on the keypad

97
     Right control key

98
     Divide key on the keypad

99
     System Request/Print Screen key

100
     Alternative Graphic key

102
     Home key

103
     Up arrow key

104
     Page up key

105
     Left arrow key

106
     Right arrow key

107
     End key

108
     Down arrow key

109
     Page down down

110
     Insert key

111
     Delete key

119
     Pause/Break key

125
     Left Super key

126
     Right Super key

127
     Application Menu key

Keyboard Layouts
****************

Keyboard layouts are compiled from one or more files. When compiling a layout from multiple files, it is important that the files are specified in the correct order. The general rule is that the layout file, for example the Swedish QWERTY-keyboard, is specified first and is followed by add-ons such as the compose table and layout modifiers. mds-kbdc is used to compile layouts.

Installed keyboard layout files are located in /usr/share/mds/keyboard. (If you are hacking in the source tree, you will find this under res/keyboard.) Layouts are located in the subdirectory layout, modifiers are located in the subdirectory mods and compose tables are located in the subdirectory compose. mds-kbdc prefixes /usr/share/mds/keyboard unless the specifed files starts with /, ./ or ../. Dead keys are implemented by compose tables and not in the layouts.

Keyboard Layout Syntax
======================

Similar to the C programming language, keyboard layout files are parsed from the top down. This means that any function or macro can only be used from lines below the definition of said callable. However, the order of the mapping statements themself, in respect to each other, does not matter. Additionally, the layout files are parsed line by line, and leading whitespace is ignored. Comment can be started with a #-character and end at the end of the line. It is important to know that modifiers like Shift and Control needs to be mapped from a keycode, this and similar that many keyboards have in common, except dead key composition and compose sequences, is already available in the layout/common directory and can be included from the layout file. Compositions are implement in the compose directory and should be selected by the user at compile-time. Keyboard layout files must be written in UTF-8 (without UTF-8 BOM) and with line feeds for new lines.

Mapping Statements
------------------

The most fundamental part of the layout files are mapping statements. These specify which keycode the keys have and what happens when certain keys pressed, combined or pressed and a sequence. If we want to map keycode 57 to the space key we write

     <keycode 57> : <space>

but then we also want the space key to product a blank space when we are writting so we add

     <space> : " "

giving us

     <keycode 57> : <space>
     <space> : " "

Because the order of the mapping statements does not matter we can just as well write

     <space> : " "
     <keycode 57> : <space>

" " represents a text string with one blank space, but it is possible to have multiple characters.

If we want to extend this to altgr+space producing a no-break space, we can add either of the lines

     <altgr space> : "\u00A0" # no-break space (# comment)
     <altgr keycode 57> : "\u00A0" # no-break space

However, we also need a mapping to altgr:

     <keycode 100> : <altgr>

If we want to add a mapping to ultra from altgr+menu we can write

     <keycode 127> : <menu>
     <altgr menu> : <-altgr ultra>

-altgr means that altgr should not be reported as held down.

As can be seen in these examples it is not possible to distinguish between modifiers and keys. It is up to the keyboard layout server and keyboard layout compiler to know this. However, it is defined in the keyboard layout files whether modifiers keys are lock keys or not. To map the keycode 58 to caps lock, write

     <keycode 58> : <caps lock>

But if you do not want it be a lock key, but instead be required to be held down, similar to how is normal for Shift, instead write

     <keycode 58> : <caps>

Any modifier may be a lock key.

Another, just as important, use of mappings to is map letter keys. Unlike Control keys like Space and Shift, there are no predefined letters (With letters with mean any character other than space.). Therefore the letter is prefixed with the word `letter'. For example:

     <keycode 16> : <letter q>     # The Q-key has keycode 16 (on QWERTY)
     <letter q> : "q"              # The Q-key should produce a `q'
     <shift letter q> : "Q"        # but `Q' when shift is used
     <caps q> : "Q"                # or when caps is used
     <shift caps letter q> : "q"   # but not when both are used

Special characters like simple double quotes, backspace and, in <>-notation, greater than sign must be escaped with a prepending backslash.

Many keyboard layouts also have dead keys. Dead keys are keys that affect the next key-press. For example, `´' followed by `e' may product `é'. compose may be a dead key, just like it is in X.org, but it can also be a modifer.

To define ´, with keycode 13, compose, with keycode 125, as a dead keys write

     <keycode 13> : <dead letter ´>
     <keycode 125> : <dead compose>

Some may appear on multiple locations on the keyboard, for example, there may be a left and a right Shift key, and a normal Return key and one on the keypad:

     <keycode 42> : <left shift>
     <keycode 54> : <right shift>
     <keycode 28> : <return>
     <keycode 96> : <keypad return>

Because <left> and <right> are valid keys --- they are arrow keys --- it is important to place them directly before the key, and not after. For instance <left shift> denotes the left Shift key, whilst <shift left> denotes the Left arrow key with a Shift key held down. Modifiers goes first.

Mapping to <void> can be used to suppress an inferred mapping. For example,

     <num keycode 28> : <void>

removes all actions from the normal Return key when Num is active. Note well, this cannot be used to remove an explicit mapping. Explicit mappings may not conflict.

Sequence Mapping
----------------

Compose tables use mapping statements to map key sequences. For example the compose key followed by two `s':es makes an `ß':

     <dead compose> "s" "s" : "ß"

It is also possible to map a sequence to another sequence:

     <dead compose> <tab> : <tab> <tab> <tab> <tab>

Of course, the input does not need to be a sequence:

     <super tab> : <tab> <tab> <tab> <tab>

An alternative to Compose as a dead key, is Compose as a modifier. If you use this, the compose table need to be written for just that. There two ways do this this. Either you can write for example

     <compose "s"> <compose "s"> : "ß"

This maps two `s':es to a `ß', but requires that Compose is held down during both key-presses. The other way is to write

     <compose "s", "s"> : "ß" # Note the `,'

This also requires that compose is not released between the key-presses.

The compose table is filled with compositions where it does not matter in which order you press some of the keys. For example, instead of

     <dead compose> "S" "|" : "$"
     <dead compose> "|" "S" : "$"

you can write

     <dead compose> ("S" "|") : "$"

( ) denotes an unordered subsequence. You can also use [ ] for alternation. For example, instead of

     <dead compose> ("S" "|") : "$"
     <dead compose> ("s" "|") : "$"

you can write

     <dead compose> (["S" "s"] "|") : "$"

Inside an alternation you can use a dot for specify that no key press is needed. For example, instead of

     <dead compose> "|" "S" : "$"
     <dead compose> "|" "|" "S" : "$"

you can write

     <dead compose> "|" ["|" .] "S" : "$"

It is undefined in which order alternations and unordered subsequences are expanded; neither sequencewise or levelwise. Thus, there should not be side-effects where either one is used, nor does it make since to nest the two constructs in any other way than alternation or unordered subsequence inside unordered subsequence. The compiler may however choose to discourage unordered subsequence inside unordered subsequence because of readability issues.

Unordered subsequences longer than 5 elements cannot compile under normal circumstances. Eliminiation of unordered subsequences grows superexponentially, and thus is probably an error than can cause memory exhaustion and unrealistic compilation-time. Therefore, if an unordered subsequences longer than 5 elements is used the compiler required that the --force flag is used and that the unordered subsequences uses double brackets:

     <dead compose> ("1" "2" "3" "4" "5") : "120"
     <dead compose> (("1" "2" "3" "4" "5" "6")) : "720"
     <dead compose> (("1" "2" "3" "4" "5" "6" "7")) : "5040"
     <dead compose> (("1" "2" "3" "4" "5" "6" "7" "8")) : "40320"
     <dead compose> (("1" "2" "3" "4" "5" "6" "7" "8" "9")) : "362880"

Keyboard Layout Identification
------------------------------

Whilst it is possible to write a comment that states what keyboard layout a file implements, there is a standardise way to do this in code. The intention with this is to make it possible for graphical tools to easily list the layouts and easy to understand descriptions.

There are three things a keyboard layout file should specify: the language, the country where it is used, and the variant.

For example the Swedish QWERTY layout used in Sweden would have the code.

     information
       language "Swedish"
       country "Sweden"
       variant "QWERTY"
     end information

If the layout is used multiple countries, or even for multiple lanuages, country and language may be specified on multiple lines. For example:

     information
       language "Spanish"
       country "Argentina"
       country "Bolivia, Plurinational State of"
       country "Chile"
       country "Colombia"
       country "Costa Rica"
       country "Cuba"
       country "Dominican Republic"
       country "Ecuador"
       country "El Salvador"
       country "Guatemala"
       country "Haiti"
       country "Honduras"
       country "Mexico"
       country "Nicaragua"
       country "Panama"
       country "Paraguay"
       country "Peru"
       country "Puerto Rico"
       country "Uruguay"
       country "Venezuela, Bolivarian Republic of"
       variant "Latin American, QWERTY"
     end information

or

     information
       language "Norwegian"
       language "Bokmål"
       language "Nynorsk"
       country "Norway"
       variant "QWERTY"
     end information

Layout Assumptions
------------------

When writing generic compose tables it can be helpful to let the compiler assume that a certain set of keys will be provided by the layout file and not making other assumptions. This is helpful because if you want to make an compose table that can compose all characters given only the ASCII letters, modifiers and a compose key, rather than written a phony layout file and select it each time you compile to compose table you can state in the compose table file that the compiler should as that those keys are provided when the compose table file is compile by itself. If this is done, the compiler can warn when one of the compositions cannot be reached from those basic keys.

If we want to make the compiler assume that compose is available as a dead key, that shift, altgr and space are available and that the ASCII letters, digits and some basic special characters are available we can write.

     assumption
       have <dead compose>
       have <shift>
       have <altgr>
       have <space>
       have_range "0" "9"
       have_range "a" "z"
       have_range "A" "Z"
       have_chars "!\"@#$%&/{([)]=}?\\^~*'<>|,;.:-_"
     end assumption

Include Statement
-----------------

Writing layout files from scratch is probably something you want to avoid. For instance you would we need to create mappings for `A' to `Z' and `0' to `9' (assuming its a latin-based language), and map up all specific key, like modifiers, space, arrow keys, and the keypad. And you would have to make sure do only that the keys are mapped but that they are mapped to the text the should product and that they word correcly with the modifiers. These are things most keyboards have in common with many other layouts.

For instance layout/sv/qwerty has two include statements to implement its basics:

     include "../common/qwerty"
     include "../common/base"

Layout Macros and Functions
---------------------------

There is a lot of repetitive work in layouts, for instance all letters need mapping for any combination of use of shift and compose. To reduce this, you can define macros.

For example instead of writing

     <letter a> : "a"
     <shift letter a> : "A"
     <caps letter a> : "A"
     <shift caps letter a> : "a"

     <letter b> : "b"
     <shift letter b> : "B"
     <caps letter b> : "B"
     <shift caps letter b> : "b"

     # and so on ...

you can use a macro and write

     macro letter/2
       <letter \1> : "\1"
       <shift letter \1> : "\2"
       <caps letter \1> : "\2"
       <shift caps letter \1> : "\1"
     end macro

     letter("a" "A")
     letter("b" "B")
     # and so on ...

The name of this macro is letter/2, but it is called with the name letter and two arguments. The /2-suffix means that it is invoked with exactly two arguments. You can use this do define multiple version of the same macro, with the same invocation name but with different number of arguments. For example:

     macro letter/2
       <letter \1> : "\1"
       <shift letter \1> : "\2"
       <caps letter \1> : "\2"
       <shift caps letter \1> : "\1"
     end macro
     macro letter/1
       letter(\1 \add(\sub(\1 "a") "A"))
     end macro

     letter("a")
     letter("b")
     # and so on ...
     letter("å" "Å")
     letter("ä" "Ä")
     letter("ö" "Ö")

\add( ) and \sub( ) are calls to two built-in functions named add/2 and sub/2.

Alternation can be used to invoke a macro:

     letter(["a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m"])
     letter(["n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"])

You may use . in an alternation, in that case macro is called once with the argument, causing it to invoke for example letter/0 instead of letter/1.

A related issue are for-loops. If we for example want to call the macro letter/1 for all letters between and including `a' and `z' we can just write

     for "a" to "z" as \1
       letter(\1)
     end for

instead of using the alternation-trick.

You call also use if-statments. For example

     for "à" to "þ" as \1
       # times sign is not upper case of division sign
       if \not(\equals(\1 "\u00F7"))
         letter(\1 \add(\sub(\1 "à") "À"))
       end if
     end for

or equivalently

     for "à" to "þ" as \1
       if \equals(\1 "\u00F7")
         continue # times sign is not upper case of division sign
       end if
       letter(\1 \add(\sub(\1 "à") "À"))
     end for

continue can be used to stop the iteration of the innermost for-loop and skip to the next iteration. You can also use break, but it also has the effect to stop the entire loop. Similarly, return can be used to break an entire macro call, or function call.

You can also use if for more example things, and use else if and else if:

     macro latter/1
       if \not(\greater(\1 "z"))
         letter(\1 \add(\sub(\1 "a") "A"))
       else if \not(\greater(\1 "þ"))
         letter(\1 \add(\sub(\1 "à") "À"))
       else
         letter(\1 \sub(\1 1))
       end if
     end macro

Note that there is no quotes around the `a' in letter(\1 \sub(\1 1)). This means that the argument will be than value 1 rather than the code point of the character `1'. Note however that values lower than zero or equals to or greater than 2 to the power of 31 not allowed and can either cause compile-time error or erroneous compiled files.

Functions are similar to function macros, the difference is that a function is called inline and is prefixed with slash, and rather than inline the code inside it, the evalutes to the last value it evaluted before it returned.

For example instead of \not(\greater(\1 "z")) you can write \less_eq(\1 "z") after you have defined the function less_eq/2 with the following code:

     function less_eq/2
       \not(\greater(\1 \2))
     end function

A final construct to make layout code less repetitive is let-statements. This can be used to assign values to variables.

The code

     macro latter/1
       if \not(\greater(\1 "z"))
         letter(\1 \add(\sub(\1 "a") "A"))
       else if \not(\greater(\1 "þ"))
         letter(\1 \add(\sub(\1 "à") "À"))
       else
         letter(\1 \sub(\1 1))
       end if
     end macro

can equivalently be written using let as

     macro latter/1
       if \not(\greater(\1 "z"))
         let \2 : \sub("a" "A")
       else if \not(\greater(\1 "þ"))
         let \2 : \sub("à" "À")
       else
         let \2 : 1
       end if
       letter(\1 \sub(\1 \2))
     end macro

It is also possible to declare arrays:

     let \1 : { "å" "ä" "ö" "à" "é" "ü" }

Arrays may however not have arrays for values.

Because arrays can be very large, they, but only them, may span multiple lines. For example you may write

     let \1 : {
       "å" "ä" "ö" "à" "é" "ü"
       }

but not

     let \1 :
       { "å" "ä" "ö" "à" "é" "ü" }

See Builtin Functions for how they are used.

Variable names can only be numerical and most not start with a zero. `0' is not valid variable name, and thus \0 does not address a variable. Macro and function names, may only include `0'--`9', `a'--`z', `A'--`Z' and `_', but must and not start with `0'--`9'. Additionally, when declared macro and function names must be suffixed with `/' follwed by the exact number of arguments the macro or function takes.

Variable indices are constrained to the 31:th power of 2, exclusively. Attempts to use higher variable indices invoke undefined behaviour. Additionally there is no guarantee that the compiler allocates indexwise spares variables efficiently.

Like variables, the size of arrays are also restricted to the 31:th power of 2.

Escaping
--------

Similar to most, if not all, programming language, a backslash inside quotes can be used to parse the next character with special meaning. For instance, `\"' is parsed as a literal `"', and `\\' is parsed as a literal `\'. `\>' is too parsed as a literal `>', for example you may need to write <letter \>>. The characters `(', `)', `[', `]', `{', `}', `<' and `,' also follow this rule to make those character accesible inside a < >. But `\' can also be used to specify characters by their code point, for example if you want an `æ' you can write "\u00E6" or "\uE6", instead of "æ". You can also write "\0346", the difference between \0 and \u is that \0 uses octal whereas \u uses hexadecimal. A noteworthy side-effect of this is that function names cannot start with a lower case `u'.

`\' can also be used to access variables and parameters. For example \1 in

     macro letter/2
       <letter \1> : "\1"
       <shift letter \1> : "\2"
       <caps letter \1> : "\2"
       <shift caps letter \1> : "\1"
     end macro
     letter("å" "Å")

is expanded to an `å', where as \2 is expanded to an `Å'.

`\' is also used to call functions, for example if you want to call the function f/0 you write \f().

Because numerical (possibly prefixed with an `u') are of variable length, it is possible to specify the escape's termination point with a dot. For instance, if you want the value of the first variable (\1) followed by two zeroes, you do not write \100 as that would expand to the value of the hundredth variable. Instead you write \1.00.

Use of function calls and variables inside include-statments invokes undefined behaviour. Escaped numerals greater than or equal to the 31th power of 2 also invoke undefined behaviour.

Builtin Functions
=================

To help you write meaningful functions in your keyboard layout files, the compiler defines an almost minimal set of basic functions:

add/2
     The code points in \1 plus the code points of the corresponding characters in \2. If \1 and \2 are not of the same length, the returned string will be of the length of the longer of the parameters, and modulo is used to map to the corresponing character.

sub/2
     Like add/2 but subtraction.

mul/2
     Like add/2 but multiplication.

div/2
     Like add/2 but division.

mod/2
     Like add/2 but modulo.

rsh/2
     Like add/2 but rightward bitwise shift. If a character in \2 is has a code point greater than 30, undefined behaviour is invoked.

lsh/2
     Like add/2 but leftward bitwise shift. If a character in \2 is has a code point greater than 30, undefined behaviour is invoked.

or/2
     Like add/2 but bitwise OR.

and/2
     Like add/2 but bitwise AND.

xor/2
     Like add/2 but bitwise XOR.

not/1
     For each character in \1, evaluate to zero if the character is not zero, and one if the character is zero.

equals/2
     For each character, evalute to one if the characters in \1 and \2 are equal and zero otherwise.

greater/2
     Like equals/2 but \1 greater than \2 rather than \1 equals \2.

less/2
     Like equals/2 but \1 less than \2 rather than \1 equals \2.

set/3
     Set the element with index \2, in the array with variable index \1, to \3, and return \3. For example \set(1 0 4) sets the first element in \1 to 4.

get/2
     Return the element with index \2 in the array with variable index \1. For example after \set(1 0 4) or let \1 : { 4 3 2 1 0 } has been used, \get(1 0) evaluates to 4.

Default Keyboard Layouts
************************

The chapter is about the special keyboard layouts and compose tables included with mds.

Dead Compose Table
==================

This section describes the structure for the mappings used in the compose table for the dead key version of the compose key.

Arrows
------

970

Basic Latin
-----------

125

Block Elements
--------------

1648

Box Drawing
-----------

Most of the box drawing glyphs can be composed by typing <dead compose> followed by two glyphs that should be combined to form the desired glyphs. If the two glyphs are identical the glyph becomes heavy. More general, common parts of the glyphs become heavy.

Glyphs that contain a heavy part be transformed so that the heavy parts become double stroked. Glyphs that do not contain heavy parts be transformed so the entire glyphs becomes double stroked. This is done by typing <dead compose> followed by, in any order, "+" and the glyph to modify. Note that this is not possible for all glyphs, as not all glyphs have a double stroked variant, but all double stroked glyphs can be composed this way.

The horizontal and the vertical light glyphs, as well as the combination of the two, can be made double stroked by typing <dead compose> followed by, in any order, "=" and the glyph.

The light corners can be made rounded by by typing <dead compose> followed by, in any order, "o" and the glyph or "O" and the glyph.

The sequences <dead compose> "-" "|" and <dead compose> "|" "-" can be used to create a light horizontal line crossed with a light vertical line.

Basic box drawing glyphs are created with sequences starting either with <shift dead compose> "b" or <shift dead compose> "B". The former creates light glyphs, and the latter creates heavy glyphs. Note that glyphs with diagonal lines do not have an heavy variants. The base sequences are followed by a sequence describing the glyphs to compose.

"-"
     Horizontal line.

"|"
     Vertical line.

"+"
     Horizontal line combined with vertical line.

"/"
     Diagonal upper right to lower left.

"\"
     Diagonal upper left to lower right.

"X"
     Diagonal cross.

"<"
     Left part of a horizontal line.

"^"
     Upper part of a vertical line.

">"
     Right part of a horizontal line.

"v"
     Lower part of a vertical line.

Simple arrows can be used instead of "<", "^", ">" and "v".

"-", "|" can be prefixed with a key to modify the lines.

"="
     Double stroke. This modifier is also available for "+".

"."
     Triple dash.

":"
     Quadruple dash.

Double dashed horizonal line is composed with <shift dead compose> "b" "." "." for the light variant and <shift dead compose> "B" "." "." for the heavy. variant. "." ":", or a broken pipe, instead of "." "." can be used to create a double dashed vertical line.

Braille Patterns
----------------

The sequence <shift dead compose> "b" <space> can be used to create a blank braille pattern.

A single-dot braille pattern can be composed with <shift dead compose> "b" followed by a digit key between "1" and "8", representing the index of the dot.

A dual-dot braille pattern can be composed with <shift dead compose> "B" followed by two digit keys between "1" and "8", representing the indices of the dots.

More complex braille patterns are composed by overlaying two braille patterns. This is done by typing <dead compose> followed by the two braille patterns to overlay. If the two braille patterns are identical, the braille pattern will be overlays with its mirror pattern.

Domino Tiles
------------

There are two types of domino tile glyphs: horizontal and vertical. Each tile has two halfs with 0 to 6 dots. Additonally there is one horizontal tile, and one vertical tile, with the back facing the user.

Horizontal tiles are composed with <shift dead compose> "d" "t" "-" followed by the number of dots on the left side and the number of dots on the right side. Horizontal tile with the back facing the user is composed with either "-" or <space> instead of the two digits.

Vertical tiles are composed with <shift dead compose> "d" "t" "|" followed by the number of dots on the top and the number of dots on the bottom. Vertical tile with the back facing the user is composed with either "|" or <space> instead of the two digits.

Enclosed Alphanumeric Supplement
--------------------------------

1476

Enclosed Alphanumerics
----------------------

3133

General Punctuation
-------------------

730

Geometric Shapes
----------------

1687

Geometric Shapes Extended
-------------------------

3194

IPA Extensions
--------------

568

Latin Extended-A
----------------

236

Latin Extended-B
----------------

364

Latin Extended-C
----------------

2834

Latin-1 Supplement
------------------

136

Mahjong Tiles
-------------

Unnumbered mahjong tiles are composed with <shift dead compose> "m" "t" followed by one additional key:

<
     West tile

v
     South tile

>
     East tile

^
     North tile

r
     Red dragon tile

g
     Green dragon tile

w
     White dragon tile

m
     Plum (mei) tile

l
     Orchid (lan) tile

z
     Bamboo (zhu) tile

j
     Chrysanthemum (ju) tile

1
     Spring tile

2
     Summer tile

3
     Autumn tile

4
     Winter tile

*
     Joker tile

/
     The back of a mahjong tile

The numbered tiles are composed with <shift dead compose> "m" "t" followed by with additional keys: one for the suit, and one for the value. The value is is encoded with either "1" to "9". The suits is encoded

W
     Characters (wan)

T
     Bamboos (tiao)

B
     Circles (bing)

Mathematical Operators
----------------------

1118

Miscellaneous Mathematical Symbols-A
------------------------------------

1824

Miscellaneous Mathematical Symbols-B
------------------------------------

2119

Miscellaneous Symbols and Arrows
--------------------------------

2594

Number Forms
------------

889

Playing Cards
-------------

<shift dead compose> "p" "c" composes the character presenting the back of a playing card.

Jokers and trumps are composed using the playing card back and two additional characters.

joker, red
     <dead compose> <playing card back> "j" "r"

joker, white
     <dead compose> <playing card back> "j" "w"

joker, black
     <dead compose> <playing card back> "j" "b"

The red joker can be composed with the sequence <dead compose> <shift dead compose> "p" "c" "j" "r", becuase <playing card back> can be composed with the sequence <shift dead compose> "p" "c".

The trumps are number 1 through 21, and are composed with <dead compose> <playing card back> "1" <space> through <dead compose> <playing card back> "2" "1". Additionally, the fool card is composed with through <dead compose> <playing card back> "0" <space>.

The Playing Cards block in Unicode also contains ace, 2--10, jack, knight, queen och king for the suits spades/swords, hearts/cups, diamonds/pentacles and clubs/wands. These are composed with the <dead compose> followed by, in any order, the suit and value. The values are encoded

Ace
     "A", "a" or "1"

2--9
     "2" through "9"

10
     "0"

Jack
     "J" or "j"

Knight
     "C" or "c"

Queen
     "Q" or "q"

King
     "K" or "k"

and the suits are encoded

Spades or Swords
     Black or white spades symbol

Hearts or Cups
     Black or white hearts symbol

Diamonds or Pentacles
     Black or white diamonds symbol

Clubs or Wands
     Black or white clubs symbol

Superscripts and Subscripts
---------------------------

840

Supplemental Arrows-A
---------------------

1900

Supplemental Arrows-B
---------------------

1973

Supplemental Arrows-C
---------------------

3284

Supplemental Mathematical Operators
-----------------------------------

2286

Tags
----

The ``Tags'' block in Unicode has been deprecated. Characters in this block is therefore not mapped in the compose table.

Variation Selectors
-------------------

There are 256 variation selectors, numbered 1 through 256. These can be composed with the sequence <shift dead compose> "v" "s" followed by exactly three digits. These digits should form the index of the variation selector. Indices lower than 100, require leading "0":s. Alternatively, variation selectors with an index lower than 100, can be composed with a trailing <space> instead of leading "0":s.

Accessibility
*************

Sticky Keys
===========

Sticky keys is an accessibility feature that lets the user process modifier keys instead of holding them down. Sticky keys is implemented by the mds-keystick server.

When mds-keystick is active, any key that is mapped in mds-keystick to be a modifier is held down once press and not released until an non-modifier is released. It is possible for map any key to have this feature, that do not have to be actual modifiers, that is, modifiers according to mds-keytrans.

If a key is press three times without any intermediate keys, and is a modifier, that key released until it is pressed again.

Note that mds-keystick is not aware of which keys are considered modifiers by mds-keytrans, but it is affected of remappings in mds-kbd and mds-kkbd, therefore it is better to swap, for example, control and caps lock in the keyboard servers than in mds-keytrans. Doing so means that you do not have to configure mds-keystick to know the original caps lock is a modifier but the original control is not.

For greater accessibility you can, in mds-keytrans, replace a key with the mode lock-key. If this is done, pressing a sequence of modifiers and then the mode lock-key will caused those modifiers to be locked until the next time you press mode lock. Any modifier pressed directly before, optionally with intermediate modifiers, the second mode lock will stay locked. The action of mode lock is to release all modifiers it is locked and the lock those that are currently held down; active stickly keys are artificially held down and thus included.

Bounce Keys
===========

Bounce keys is an accessibility feature that filters out rapidly repeated key strokes. Bounce keys is implemented by the mds-keybounce server.

Slow Keys
=========

Slow keys is an accessibility feature that filters out brief key strokes. Slow keys is implemented by the mds-slowkey server.

Loud Keys
=========

Loud keys is an accessibility feature that can emulate key clicking sounds when a key is pressed or generate tones when certain keys are pressed. For example if caps lock is actived by a key stroke a high-pitched tone can be generated when when it is deactived by a key stroke a low-pitched tone can be generated. Loud keys is implemented by the mds-keycue server.

Mouse Keys
==========

Rat keys (also known as mouse keys) is an accessibility and usability feature that lets the user use the keyboard as a pointing device. This feature is implemented by the mds-kbd2rat server, and this section covers the details of that server.

If mds-kbd2rat is used, the keypad acts as a pointing device when num lock is not active. It is also possible to configure mds-kbd2rat to disregard num lock and always be active, until it receives a signal to toggle its state. For example, if mds-kbd2rat is configured to disregard num lock, mds-kbdtrans can be configured to send to fauxkey rat when alt+shift+num is pressed, and this key can be caught by mds-keybind that sends a signal to mds-kbd2rat to toggle.

When mds-kbd2rat is active, it maps the keypad to the rat according to the following table:

division
     Right-hand left (primary) rat button.

multiplication
     Middle (modifier) rat button.

subtraction
     Right-hand (alternate) right rat button.

addition
     Scroll up.

return
     Scroll down.

comma
     Cancel actions waiting by 0 and 5.

0
     Hold down the next selected rat button until that rat button is selected again. This is a dead key, that is, you do not have to hold it down.

1
     Cursor left down.

2
     Cursor down.

3
     Cursor right down.

4
     Cursor left.

5
     Double click with the next selected rat button. This is a dead key, that is, you do not have to hold it down. If pressed twice, a triple click triggered instead, and so on. If this key is prefixed by 0, the last click will be replaced by hold down action.

6
     Cursor right.

7
     Cursor left up.

8
     Cursor up.

9
     Cursor right up.

This table is not affected by mappings in mds-keytrans, but it is affected by remappings in mds-kbd and mds-kkbd.

mds-kbd2rat can be configured to permute the rat button keys. It is independent of permutations in mds-rat.

If multiple direction keys (1, 2, 3, 3, 4, 6, 7, 8 and 9) are used, the average direction is used.

mds-kbd2rat is five parameters that control with which speed it moves the cursor:

delay
     The delay it takes before the first time a mouse event is repeated when a key is held down. The default is for the server to wait for the keyboard to send another key press.

interval
     The time it takes before a mouse event is repeated since its previous repear when a key is held down. The default is for the server to wait for the keyboard to send another key press.

max speed
     The maximum speed with which the cursor can move.

time to max speed
     The time a key has to be held down before the maximum speed is reached. The cursor accelerate with each mouse event repeat.

curve
     Ramp used to reach pointer speed.

The pointer's speed, not taking caps into consideration, is calculated by

max speed ((hold down time - delay) / time to max speed)^(1 + curve)

Specifications
**************

Rat Cursors
===========

Rat cursor themes should not add shadows to the cursors. Shadows are added by the mds-cursorshadow server according to the user's specifications.

mds's rat cursors specifications are based on http://www.freedesktop.org/wiki/Specifications/cursor-spec.

All rat cursor themes should include the cursors listed below. The icons are conceptual examples of how they can look.

In addition to the cursors below, each of the may be accompanied with X-press, X-hold and X-release, where X is the name of the master icon. X-press is an animation from X to X-hold and is used when the cursor should transition from X to X-hold. X-hold is the version of X that should be used if any rat button is held down. X is an animation from X-release to X and is used when the cursor should transition from X-release to X. Clients should not set the cursor to either of them, it is up to the server to do this based on events from the rat device.

default
     This is the default cursor. It is used as a fallback if no more fitting cursor is found; for example if a programs wants the cursor to be pointer, but the server is unable to find it, it will fallback to default. The server should provide its own fallback in case the theme is missing this cursor too.

     This cursor indicates that the interface is idle and prepared to accept commands from the user.

     This cursor is usually a north-west- or north-north-west-pointing arrow. For left-handed themes this cursor is usually a north-east- or north-north-east-pointing arrow.

          ##
          ####
          ######
          ########
          ##########
          ############
          ##############
          ################
          ##################
          ############
          ######  ####
          ####    ######
          ##        ####
                    ######
                      ####
                      ####

context-menu
     This cursor indicates the same state as default with he addition that the object beneath it can be right-clicked (left-clicked if left-handed) to open a context menu.

     This cursor is typically default combined with a small menu.

          ##                  ############
          ####                ############
          ######              ##        ##
          ########            ############
          ##########          ##        ##
          ############        ############
          ##############      ##        ##
          ################    ############
          ##################
          ############
          ######  ####
          ####    ######
          ##        ####
                    ######
                      ####
                      ####

text
     This cursor should be used when the rat pointers is above an horizontal text that can be selected and possibly edited.

     This cursor is usually a vertical I-beam.

          ##############
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
          ##############

vertical-text
     This cursor should be used when the rat pointers is above an vertical text that can be selected and possibly edited.

     If this cursor is missing, text should be used as the first fallback.

     This cursor is usually a horizontal I-beam.

          ##                            ##
          ##                            ##
          ##                            ##
          ################################
          ##                            ##
          ##                            ##
          ##                            ##

progress
     This cursor indicates that the interface can be used as when default is used. But that the program is working in the background with command the user previously issued.

     This cursor is usually rendered as a combination of default and wait.

          ##                  ############
          ####                ############
          ######                ########
          ########                ####
          ##########              ####
          ############          ########
          ##############      ############
          ################    ############
          ##################
          ############
          ######  ####
          ####    ######
          ##        ####
                    ######
                      ####
                      ####

wait
     This cursor indicates that the interface cannot be used because it is working or is blocked by an external resource.

     This cursor is typically rendered as a hourglass, watch, sundial or some sort of animated ring.

                ####################
                ####################
                  ################
                    ############
                      ########
                        ####
                        ####
                        ####
                        ####
                        ####
                        ####
                      ########
                    ############
                  ################
                ####################
                ####################

pointer
     This cursor indicates that the object beneath it is clickable. Typically a link in a Web browser. However, it should not be used for pushbuttons and other user interface elements where it is apparent by design that the object is clickable.

     This cursor is usually a right hand (left hand if left-handed) pointing with the index-finger.

                  ####
                  ####
                  ####
                  ####
                  ####  ####
                  ####  ####  ####
            ##    ####  ####  ####  ####
          ######  ################  ####
            ##############################
              ############################
                ##########################
                ##########################
                  ########################
                  ########################
                    ####################
                      ################

help
     This cursor indicates that the interface is in context help mode. This is usually activated by clicking an help button --- which usally has a question mark on it --- on the titlebar.

     This cursor is typically renderas as default with a question mark next to it.

          ##                ######
          ####            ##########
          ######        ####      ####
          ########                ####
          ##########            ####
          ############        ####
          ##############      ####
          ################    ####
          ##################
          ############        ####
          ######  ####        ####
          ####    ######
          ##        ####
                    ######
                      ####
                      ####

drag
     This cursor indicates that an object is being dragged.

     This cursor is usually a closed right hand, or closed left hand if left-handed.

              ####  ####  ####
              ################  ####
          ############################
          ############################
          ############################
            ##########################
              ########################
              ########################
                ####################
                  ################

copy
     This cursor indicates that the dragged object will be copied or listed upon release.

     If this cursor is missing, drag should be used as the first fallback.

     This cursor is usually rendered as drag with a plus-sign next to it.

                                    ##
                                    ##
                                ##########
                                    ##
                                    ##

              ####  ####  ####
              ################  ####
          ############################
          ############################
          ############################
            ##########################
              ########################
              ########################
                ####################
                  ################

move
     This cursor indicates that the dragged object will be moved upon release, or otherwise acted upon.

     If this cursor is missing, drag should be used as the first fallback.

     This cursor is usually rendered as drag with an arrow next to it. The arrow is usually point north-east, or north-west if left-handed.

                                ######
                                ####
                                ##  ##
                                      ##
                                        ##

              ####  ####  ####
              ################  ####
          ############################
          ############################
          ############################
            ##########################
              ########################
              ########################
                ####################
                  ################

alias
     This cursor indicates that the dragged object will be aliased upon release, or otherwise acted upon. This may entail creating a symlink.

     If this cursor is missing, drag should be used as the first fallback.

     This cursor is usually rendered as drag with an two or three linked links next to it, or an arced arrow.

                            ####    ####
                          ##            ##
                          ##  ########  ##
                          ##            ##
                            ####    ####

              ####  ####  ####
              ################  ####
          ############################
          ############################
          ############################
            ##########################
              ########################
              ########################
                ####################
                  ################

no-drop
     This cursor indicates that the dragged object cannot be release where the rat pointer is located, but that the object beneath it usually allow drops of objects with similar class to the dragged object.

     If this cursor is missing, not-allowed should be used as the first fallback, and drag should be used as the second fallback.

     This cursor is typically rendered as a combination of drag and not-allowed.

                                ########
                              ##      ####
                              ##    ##  ##
                              ##  ##    ##
                              ####      ##
                                ########
              ####  ####  ####
              ################  ####
          ############################
          ############################
          ############################
            ##########################
              ########################
              ########################
                ####################
                  ################

not-allowed
     This cursor indicates that the region beneath the rat pointer is invalid for the current operation.

     This cursor is often rendered as a circle with a diagonal line through it.

                      ########
                  ####        ####
                ##                ##
              ##                  ####
            ##                  ##    ##
            ##                ##      ##
          ##                ##          ##
          ##              ##            ##
          ##            ##              ##
          ##          ##                ##
            ##      ##                ##
            ##    ##                  ##
              ####                  ##
                ##                ##
                  ####        ####
                      ########

all-scroll
     This cursor is used to indicate that moving the rat will also move the object beneath below the cursor

     This cursor is often rendered as a combined vertical and horizontal twin-headed arrow.

                        ##
                      ######
                    ##########
                        ##
                        ##
              ##        ##        ##
            ####        ##        ####
          ##############################
            ####        ##        ####
              ##        ##        ##
                        ##
                        ##
                    ##########
                      ######
                        ##

up-arrow
     This cursor is typically used to identify an insertion point.

     It is often rendered an upwards-pointing arrow.

                ##
              ######
            ##########
          ##############
              ######
              ######
              ######
              ######
              ######
              ######
              ######

cell
     This cursor is often used in spread-sheet applications when selecting cells.

     It is typically rendered as a thick plus-sign.

                    ######
                    ######
                    ######
                    ######
                    ######
          ##########################
          ##########################
          ##########################
                    ######
                    ######
                    ######
                    ######
                    ######

col-resize
     This cursor is used to indicate that the cursor is within a region that allows it rat to be used to resize a column.

     If this cursor is missing, ew-resize should be used as the first fallback, and ew-select should be used as the second fallback.

     This cursor is typically rendered as a vertical bar with an arrow from the left side pointing horizontally towards it and an arrow from the right side pointing horizontally towards it.

                        ##
                        ##
                        ##
                        ##
                        ##
                ##      ##      ##
                ####    ##    ####
          ############  ##  ############
                ####    ##    ####
                ##      ##      ##
                        ##
                        ##
                        ##
                        ##
                        ##

row-resize
     This cursor is used to indicate that the cursor is within a region that allows it rat to be used to resize a column.

     If this cursor is missing, ns-resize should be used as the first fallback, and ns-select should be used as the second fallback.

     This cursor is typically rendered as a horizontal bar with an arrow from the left side pointing vertically towards it and an arrow from the right side pointing vertically towards it.

                        ##
                        ##
                        ##
                    ##########
                      ######
                        ##

          ##############################

                        ##
                      ######
                    ##########
                        ##
                        ##
                        ##

crosshair
     This cursor is used for precision drawing or precision manipulation of an area.

     This cursor typically a thin crosshair.

                        ##
                        ##
                        ##
                        ##
                        ##
                        ##
                        ##
          ##############################
                        ##
                        ##
                        ##
                        ##
                        ##
                        ##
                        ##

w-resize
     If this cursor is missing, w-select should be used as the first fallback, ew-resize should be used as the second fallback, ew-select should be used as the third fallback, and col-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a west-pointing arrow, optionally with a wall at the arrowhead.

          ##        ##
          ##      ##
          ##    ##
          ##  ############################
          ##    ##
          ##      ##
          ##        ##

w-select
     If this cursor is missing, w-resize should be used as the first fallback, ew-select should be used as the second fallback, ew-resize should be used as the third fallback, and col-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a west-pointing arrow.

                ##
              ##
            ##
          ############################
            ##
              ##
                ##

e-resize
     If this cursor is missing, e-select should be used as the first fallback, ew-resize should be used as the second fallback, ew-select should be used as the third fallback, and col-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a east-pointing arrow, optionally with a wall at the arrowhead.

                              ##        ##
                                ##      ##
                                  ##    ##
          ############################  ##
                                  ##    ##
                                ##      ##
                              ##        ##

e-select
     If this cursor is missing, e-resize should be used as the first fallback, ew-select should be used as the second fallback, ew-resize should be used as the third fallback, and col-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a east-pointing arrow.

                              ##
                                ##
                                  ##
          ############################
                                  ##
                                ##
                              ##

n-resize
     If this cursor is missing, n-select should be used as the first fallback, ns-resize should be used as the second fallback, ns-select should be used as the third fallback, and row-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a north-pointing arrow, optionally with a wall at the arrowhead.

          ##############

                ##
              ######
            ##  ##  ##
          ##    ##    ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##

n-select
     If this cursor is missing, n-resize should be used as the first fallback, ns-select should be used as the second fallback, ns-resize should be used as the third fallback, and row-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a north-pointing arrow.

                ##
              ######
            ##  ##  ##
          ##    ##    ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##

s-resize
     If this cursor is missing, s-select should be used as the first fallback, ns-resize should be used as the second fallback, ns-select should be used as the third fallback, and row-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a south-pointing arrow, optionally with a wall at the arrowhead.

                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
          ##    ##    ##
            ##  ##  ##
              ######
                ##

          ##############

s-select
     If this cursor is missing, s-resize should be used as the first fallback, ns-select should be used as the second fallback, ns-resize should be used as the third fallback, and row-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a south-pointing arrow.

                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
                ##
          ##    ##    ##
            ##  ##  ##
              ######
                ##

nw-resize
     If this cursor is missing, nw-select should be used as the first fallback, nwse-resize should be used as the second fallback, nwse-select should be used as the third fallback, and all-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a north-west-pointing arrow, optionally with a corner at the arrowhead.

          ##################
          ##
          ##
          ##    ############
          ##    ####
          ##    ##  ##
          ##    ##    ##
          ##    ##      ##
          ##    ##        ##
                            ##
                              ##
                                ##
                                  ##
                                    ##
                                      ##
                                        ##

nw-select
     If this cursor is missing, nw-resize should be used as the first fallback, nwse-select should be used as the second fallback, nwse-resize should be used as the third fallback, and all-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a north-west-pointing arrow.

          ############
          ####
          ##  ##
          ##    ##
          ##      ##
          ##        ##
                      ##
                        ##
                          ##
                            ##
                              ##
                                ##
                                  ##

se-resize
     If this cursor is missing, se-select should be used as the first fallback, nwse-resize should be used as the second fallback, nwse-select should be used as the third fallback, and all-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a south-east-pointing arrow, optionally with a corner at the arrowhead.

          ##
            ##
              ##
                ##
                  ##
                    ##
                      ##
                        ##        ##    ##
                          ##      ##    ##
                            ##    ##    ##
                              ##  ##    ##
                                ####    ##
                        ############    ##
                                        ##
                                        ##
                        ##################

se-select
     If this cursor is missing, se-resize should be used as the first fallback, nwse-select should be used as the second fallback, nwse-resize should be used as the third fallback, and all-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a south-east-pointing arrow.

          ##
            ##
              ##
                ##
                  ##
                    ##
                      ##
                        ##        ##
                          ##      ##
                            ##    ##
                              ##  ##
                                ####
                        ############

ne-resize
     If this cursor is missing, ne-select should be used as the first fallback, nesw-resize should be used as the second fallback, nesw-select should be used as the third fallback, and all-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a north-east-pointing arrow, optionally with a corner at the arrowhead.

                        ##################
                                        ##
                                        ##
                        ############    ##
                                ####    ##
                              ##  ##    ##
                            ##    ##    ##
                          ##      ##    ##
                        ##        ##    ##
                      ##
                    ##
                  ##
                ##
              ##
            ##
          ##

ne-select
     If this cursor is missing, ne-resize should be used as the first fallback, nesw-select should be used as the second fallback, nesw-resize should be used as the third fallback, and all-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a north-east-pointing arrow.

                        ############
                                ####
                              ##  ##
                            ##    ##
                          ##      ##
                        ##        ##
                      ##
                    ##
                  ##
                ##
              ##
            ##
          ##

sw-resize
     If this cursor is missing, sw-select should be used as the first fallback, nesw-resize should be used as the second fallback, nesw-select should be used as the third fallback, and all-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a south-west-pointing arrow, optionally with a corner at the arrowhead.

                                        ##
                                      ##
                                    ##
                                  ##
                                ##
                              ##
                            ##
          ##    ##        ##
          ##    ##      ##
          ##    ##    ##
          ##    ##  ##
          ##    ####
          ##    ############
          ##
          ##
          ##################

sw-select
     If this cursor is missing, sw-resize should be used as the first fallback, nesw-select should be used as the second fallback, nesw-resize should be used as the third fallback, and all-resize. should be used as the fourth fallback.

     This cursor is typically rendered as a south-west-pointing arrow.

                                  ##
                                ##
                              ##
                            ##
                          ##
                        ##
                      ##
          ##        ##
          ##      ##
          ##    ##
          ##  ##
          ####
          ############

ew-resize
     If this cursor is missing, ew-select should be used as the first fallback, and col-resize. should be used as the second fallback.

     This cursor is typically rendered as an east- and west-pointing twin-arrow, optionally with a wall at the arrowheads.

          ##        ##        ##        ##
          ##      ##            ##      ##
          ##    ##                ##    ##
          ##  ########################  ##
          ##    ##                ##    ##
          ##      ##            ##      ##
          ##        ##        ##        ##

ew-select
     If this cursor is missing, ew-resize should be used as the first fallback, and col-resize. should be used as the second fallback.

     This cursor is typically rendered as an east- and west-pointing twin-arrow.

                ##        ##
              ##            ##
            ##                ##
          ########################
            ##                ##
              ##            ##
                ##        ##

ns-resize
     If this cursor is missing, ns-select should be used as the first fallback, and row-resize. should be used as the second fallback.

     This cursor is typically rendered as a north- and south-pointing twin-arrow, optionally with a wall at the arrowheads.

          ##############

                ##
              ######
            ##  ##  ##
          ##    ##    ##
                ##
                ##
                ##
                ##
          ##    ##    ##
            ##  ##  ##
              ######
                ##

          ##############

ns-select
     If this cursor is missing, ns-resize should be used as the first fallback, and row-resize. should be used as the second fallback.

     This cursor is typically rendered as a north- and south-pointing twin-arrow.

                ##
              ######
            ##  ##  ##
          ##    ##    ##
                ##
                ##
                ##
                ##
          ##    ##    ##
            ##  ##  ##
              ######
                ##

nwse-resize
     If this cursor is missing, all-resize should be used as the first fallback.

     This cursor is typically rendered as a north-west- and south-east-pointing twin-arrow, optionally with a corner at the arrowheads.

          ##################
          ##
          ##
          ##    ############
          ##    ####
          ##    ##  ##
          ##    ##    ##
          ##    ##      ##        ##    ##
          ##    ##        ##      ##    ##
                            ##    ##    ##
                              ##  ##    ##
                                ####    ##
                        ############    ##
                                        ##
                                        ##
                        ##################

nesw-resize
     If this cursor is missing, all-resize should be used as the first fallback.

     This cursor is typically rendered as a north-east- and south-west-pointing twin-arrow, optionally with a corner at the arrowheads.

                        ##################
                                        ##
                                        ##
                        ############    ##
                                ####    ##
                              ##  ##    ##
                            ##    ##    ##
          ##    ##        ##      ##    ##
          ##    ##      ##        ##    ##
          ##    ##    ##
          ##    ##  ##
          ##    ####
          ##    ############
          ##
          ##
          ##################

all-resize
     This cursor is typically rendered as a cross between a north-east and south-west-pointing twin-arrow and a north-west- and south-east-pointing twin-arrow, optionally with a corner at the arrow heads.

          ##########          ##########
          ####                      ####
          ##  ##                  ##  ##
          ##    ##              ##    ##
          ##      ##          ##      ##
                    ##      ##
                      ##  ##
                        ##
                      ##  ##
                    ##      ##
          ##      ##          ##      ##
          ##    ##              ##    ##
          ##  ##                  ##  ##
          ####                      ####
          ##########          ##########

In addition, it is advised to nwse-select and nesw-select that are rendered in the same mannar as the other *-select cursors and analogously to nwse-resize and nesw-resize, respectively.

It is also advisd to a cursors intermediate to text and vertical-text. These are named with the pattern text-*, where * is replaced by the number of degrees the text is rotated anti-clockwise. This means that text should be used if text-0 is requested but missing, and vertical-text should be used if text-90 is requested but missing. Finally, the closest existing cursor should be used, and the cursor rotated 180 degrees of what is requested should be used if there is no matching cursor with a rotation distance within, but excluding, 90 degrees. * should be in the interval [0, 360[, and a period (`.') should be used as a decimal pointer, as it is used in most programming languages.

Colour Names
============

mds protocols provide an optional way to name colours. This is used primarily for colours used by toolkits. These are called system colours. But it is also possible to have names for common colours that should be tunable. These are called named colours.

There are no colours is guaranteed to exist. Nor is it guaranteed that value of named colours reflect the names of them, in any aspect. For example `red' could be a light blue, and `light-red` could be a dark green. In fact, you use assume that the names does not reflect the actual colour. For example, if a terminal uses named colours for the colours choosen by programs via ANSI escape sequences, the use can change these colours to create a theme she likes better, even if the colours are no longer what ANSI defines them.

There is however a list of recommended colour names, with recommended definitions:

black
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequences CSI 30 m or CSI 40 m. This colour is usually pure black.

red
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequences CSI 31 m or CSI 41 m. This colour is usually a medium red.

green
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequences CSI 32 m or CSI 42 m. This colour is usually a medium green.

yellow
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequences CSI 33 m or CSI 43 m. This colour is usually a medium yellow or medium orange.

blue
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequences CSI 34 m or CSI 44 m. This colour is usually a medium blue.

purple
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequences CSI 35 m or CSI 45 m. This colour is usually a medium purple, medium lilac or medium fuchsia/magenta.

teal
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequences CSI 36 m or CSI 46 m. This colour is usually a medium teal or medium turquoise/cyan

grey
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequences CSI 37 m or CSI 47 m. This colour is usually around 50% grey.

dark-grey
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequence CSI 1 ; 30 m. This colour is usually around 25% grey.

light-red
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequence CSI 1 ; 31 m. This colour is usually the same colour as, but brighter than, red.

light-green
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequence CSI 1 ; 32 m. This colour is usually the same colour as, but brighter than, green.

light-yellow
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequence CSI 1 ; 33 m. This colour is usually a bright yellow.

light-blue
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequence CSI 1 ; 34 m. This colour is usually the same colour as, but brighter than, blue.

light-purple
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequence CSI 1 ; 35 m. This colour is usually the same colour as, but brighter than, purple.

light-teal
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequence CSI 1 ; 36 m. This colour is usually the same colour as, but brighter than, teal.

white
     It is recommended that terminals use this as the default colour for the colour selected by the ANSI escape sequence CSI 1 ; 37 m. This colour is usually a pure white or very bright grey.

background
     It is recommended that terminals use this as the default background colour. This should be noted, that it is not recommened for or programs.

foreground
     It is recommended that terminals use this as the default text colour. This should be noted, that it is not recommened for or programs.

desktop-background
     The default background colour on the desktop.

desktop-foreground
     The colour for text on icons and gadgets on the desktop.

desktop-selection
     The background for text on icons that have been selected on the desktop.

desktop-selection-foreground
     The colour for text on icons that have been selected on the desktop.

desktop-foreground-hover
     The colour for text on icons on the desktop, when the icon is being hovered.

desktop-selection-hover
     The background for text on icons that have been selected on the desktop, when the icon is being hovered.

desktop-selection-foreground-hover
     The colour for text on icons that have been selected on the desktop, when the icon is being hovered.

window-background
     The background on windows.

window-foreground
     The colour on text on windows, as well as the colour of frames.

window-foreground-disabled
     The colour on text, associated with disabled components, on windows.

window-cursor
     The colour on text cursors for selectable text on windows.

window-selection
     The colour on text-selection highlight for selectable text on windows.

window-selection-foreground
     The colour on text on selected for text on windows.

link-foreground
     The colour on text for unvisited links.

link-active-foreground
     The colour on text for links that are currently being visited.

link-visited-foreground
     The colour on text for visited links.

link-broken-foreground
     The colour on text for broken links.

link-background-foreground
     The background colour for unvisited links.

link-active-background
     The background colour for links that are currently being visited.

link-visited-background
     The background colour for visited links.

link-broken-background
     The background colour for broken links.

link-selection
     The colour on text highlight for selected text on unvisited links.

link-active-selection
     The colour on text highlight for selected text on links that are currently being visited.

link-visited-selection
     The colour on text highlight for selected text on visited links.

link-broken-selection
     The colour on text highlight for selected text on broken links.

link-selection-foreground
     The colour on selected text on unvisited links.

link-active-selection-foreground
     The colour on selected text on links that are currently being visited.

link-visited-selection-foreground
     The colour on selected text on visited links.

link-broken-selection-foreground
     The colour on selected text on broken links.

link-foreground-hover
     The colour on text for unvisited links, when the link is being hovered.

link-active-foreground-hover
     The colour on text for links that are currently being visited, when the link is being hovered.

link-visited-foreground-hover
     The colour on text for visited links, when the link is being hovered.

link-broken-foreground-hover
     The colour on text for broken links, when the link is being hovered.

link-background-foreground-hover
     The background colour for unvisited links, when the link is being hovered.

link-active-background-hover
     The background colour for links that are currently being visited, when the link is being hovered.

link-visited-background-hover
     The background colour for visited links, when the link is being hovered.

link-broken-background-hover
     The background colour for broken links, when the link is being hovered.

link-selection-hover
     The colour on text highlight for selected text on unvisited links, when the link is being hovered.

link-active-selection-hover
     The colour on text highlight for selected text on links that are currently being visited, when the link is being hovered.

link-visited-selection-hover
     The colour on text highlight for selected text on visited links, when the link is being hovered.

link-broken-selection-hover
     The colour on text highlight for selected text on broken links, when the link is being hovered.

link-selection-foreground-hover
     The colour on selected text on unvisited links, when the link is being hovered.

link-active-selection-foreground-hover
     The colour on selected text on links that are currently being visited, when the link is being hovered.

link-visited-selection-foreground-hover
     The colour on selected text on visited links, when the link is being hovered.

link-broken-selection-foreground-hover
     The colour on selected text on broken links, when the link is being hovered.

link-foreground-disabled
     The colour on text for unvisited links, when the link is disabled.

link-active-foreground-disabled
     The colour on text for links that are currently being visited, when the link is disabled.

link-visited-foreground-disabled
     The colour on text for visited links, when the link is disabled.

link-broken-foreground-disabled
     The colour on text for broken links, when the link is disabled.

link-background-disabled
     The background colour for unvisited links, when the link is disabled.

link-active-background-disabled
     The background colour for links that are currently being visited, when the link is disabled.

link-visited-background-disabled
     The background colour for visited links, when the link is disabled.

link-broken-background-disabled
     The background colour for broken links, when the link is disabled.

link-selection-disabled
     The colour on text highlight for selected text on unvisited links, when the link is disabled.

link-active-selection-disabled
     The colour on text highlight for selected text on links that are currently being visited, when the link is disabled.

link-visited-selection-disabled
     The colour on text highlight for selected text on visited links, when the link is disabled.

link-broken-selection-disabled
     The colour on text highlight for selected text on broken links, when the link is disabled.

link-selection-foreground-disabled
     The colour on selected text on unvisited links, when the link is disabled.

link-active-selection-foreground-disabled
     The colour on selected text on links that are currently being visited, when the link is disabled.

link-visited-selection-foreground-disabled
     The colour on selected text on visited links, when the link is disabled.

link-broken-selection-foreground-disabled
     The colour on selected text on broken links, when the link is disabled.

button-background
     The background colour on buttons and button-like controls.

button-foreground
     The colour on text on buttons and button-like controls.

button-aura
     The colour on aura around buttons and button-like controls to mark that they have focus.

button-background-toggled
     The background colour on buttons and button-like controls, under that condition that the button is toggled.

button-foreground-toggled
     The colour on text on buttons and button-like controls, under that condition that the button is toggled.

button-aura-toggled
     The colour on aura around buttons and button-like controls to mark that they have focus, under that condition that the button is toggled.

button-background-hover
     The background colour on buttons and button-like controls, when the button is being hovered.

button-foreground-hover
     The colour on text on buttons and button-like controls, when the button is being hovered.

button-aura-hover
     The colour on aura around buttons and button-like controls to mark that they have focus, when the button is being hovered.

button-background-toggled-hover
     The background colour on buttons and button-like controls, when the button is being hovered, under that condition that the button is toggled.

button-foreground-toggled-hover
     The colour on text on buttons and button-like controls, when the button is being hovered, under that condition that the button is toggled.

button-aura-toggled-hover
     The colour on aura around buttons and button-like controls to mark that they have focus, when the button is being hovered, under that condition that the button is toggled.

button-background-disabled
     The background colour on disabled buttons and button-like controls.

button-foreground-disabled
     The colour on text on disabled buttons and button-like controls.

button-aura-disabled
     The colour on aura around disabled buttons and button-like controls to mark that they have focus.

button-background-toggled-disabled
     The background colour on disabled buttons and button-like controls, under that condition that the button is toggled.

button-foreground-toggled-disabled
     The colour on text on disabled buttons and button-like controls, under that condition that the button is toggled.

button-aura-toggled-disabled
     The colour on aura around disabled buttons and button-like controls to mark that they have focus, under that condition that the button is toggled.

button-background-change
     The background colour on buttons and button-like controls, under the condition that the button is being clicked.

button-foreground-change
     The colour on text on buttons and button-like controls, under the condition that the button is being clicked.

button-aura-change
     The colour on aura around buttons and button-like controls to mark that they have focus, under the condition that the button is being clicked.

button-background-toggled-change
     The background colour on buttons and button-like controls, under that condition that the button is toggled and is being clicked.

button-foreground-toggled-change
     The colour on text on buttons and button-like controls, under that condition that the button is toggled and is being clicked.

button-aura-toggled-change
     The colour on aura around buttons and button-like controls to mark that they have focus, under that condition that the button is toggled and is being clicked.

button-background-hover-change
     The background colour on buttons and button-like controls, under the condition that the button is being clicked.

button-foreground-hover-change
     The colour on text on buttons and button-like controls, under the condition that the button is being hovered and clicked.

button-aura-hover-change
     The colour on aura around buttons and button-like controls to mark that they have focus, under the condition that the button is being hovered and clicked.

button-background-toggled-hover-change
     The background colour on buttons and button-like controls, under that condition that the button is toggled and is being hovered and clicked.

button-foreground-toggled-hover-change
     The colour on text on buttons and button-like controls, under that condition that the button is toggled and is being hovered and clicked.

button-aura-toggled-hover-change
     The colour on aura around buttons and button-like controls to mark that they have focus, under that condition that the button is toggled and is being hovered and clicked.

input-background
     The background colour on text-input components, such as comboboxes and text-fields, as well as lists and tables.

input-background-alternate
     The alternate background colour on text-input components, such as comboboxes and text-fields, as well as lists and tables.

input-foreground
     The colour on text on text-input components, such as comboboxes and text-fields, as well as lists and tables.

input-selection
     The colour on text highlight for selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables. This colour is usually blue.

input-selection-alternate
     The alternate colour on text highlight for selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables. This colour is usually blue.

input-selection-foreground
     The colour on selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables. This colour is usually blue.

input-mark
     The colour on text highlight for secondarily selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables. This colour is usually yellow.

input-mark-foreground
     The colour on secondarily selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables. This colour is usually yellow.

input-cursor
     The colour on the text cursor on text-input components, such as comboboxes and text-fields, as well as lists and tables.

input-aura
     The colour on the aura around text-input components, such as comboboxes and text-fields, as well as lists and tables, to mark that they have focus.

input-background-hover
     The background colour on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-background-alternate-hover
     The alternate background colour on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-foreground-hover
     The colour on text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-selection-hover
     The colour on text highlight for selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-selection-alternate-hover
     The alternate colour on text highlight for selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-selection-foreground-hover
     The colour on selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-mark-hover
     The colour on text highlight for secondarily selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-mark-foreground-hover
     The colour on secondarily selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-cursor-hover
     The colour on the text cursor on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is being hovered.

input-aura-hover
     The colour on the aura around text-input components, such as comboboxes and text-fields, as well as lists and tables, to mark that they have focus, under the condition that the component is being hovered.

input-background-disabled
     The background colour on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-background-alternate-disabled
     The alternate background colour on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-foreground-disabled
     The colour on text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-selection-disabled
     The colour on text highlight for selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-selection-alternate-disabled
     The alternate colour on text highlight for selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-selection-foreground-disabled
     The colour on selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-mark-disabled
     The colour on text highlight for secondarily selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-mark-foreground-disabled
     The colour on secondarily selected text on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-cursor-disabled
     The colour on the text cursor on text-input components, such as comboboxes and text-fields, as well as lists and tables, under the condition that the component is disabled.

input-aura-disabled
     The colour on the aura around text-input components, such as comboboxes and text-fields, as well as lists and tables, to mark that they have focus, under the condition that the component is disabled.

input-delimiter
     The colour on lines in tables used to delimit rows or coloumns.

input-delimiter-disabled
     The colour on lines in tables used to delimit rows or coloumns, when the table is disabled.

option-background
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is not checked.

option-foreground
     The colour on text for checkboxes and radioboxes, under the condition that the box is not checked.

option-aura
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is not checked.

option-background-active
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is checked.

option-foreground-active
     The colour on text for checkboxes and radioboxes, under the condition that the box is checked.

option-aura-active
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is checked.

option-background-intermediate
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked.

option-foreground-intermediate
     The colour on text for checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked.

option-aura-intermediate
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is in intermediate mode, that is, paritally checked.

option-background-hover
     The background colour for the box on hovered checkboxes and radioboxes, under the condition that the box is not checked.

option-foreground-hover
     The colour on text for hovered checkboxes and radioboxes, under the condition that the box is not checked.

option-aura-hover
     The colour of the aura around hovered checkboxes and radioboxes to mark them as having focus, under the condition that the box is not checked.

option-background-active-hover
     The background colour for the box on hovered checkboxes and radioboxes, under the condition that the box is checked.

option-foreground-active-hover
     The colour on text for hovered checkboxes and radioboxes, under the condition that the box is checked.

option-aura-active-hover
     The colour of the aura around hovered checkboxes and radioboxes to mark them as having focus, under the condition that the box is checked.

option-background-intermediate-hover
     The background colour for the box on hovered checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked.

option-foreground-intermediate-hover
     The colour on text for hovered checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked.

option-aura-intermediate-hover
     The colour of the aura around hovered checkboxes and radioboxes to mark them as having focus, under the condition that the box is in intermediate mode, that is, paritally checked.

option-background-disabled
     The background colour for the box on disabled checkboxes and radioboxes, under the condition that the box is not checked.

option-foreground-disabled
     The colour on text for disabled checkboxes and radioboxes, under the condition that the box is not checked.

option-aura-disabled
     The colour of the aura around disabled checkboxes and radioboxes to mark them as having focus, under the condition that the box is not checked.

option-background-active-disabled
     The background colour for the box on disabled checkboxes and radioboxes, under the condition that the box is checked.

option-foreground-active-disabled
     The colour on text for disabled checkboxes and radioboxes, under the condition that the box is checked.

option-aura-active-disabled
     The colour of the aura around disabled checkboxes and radioboxes to mark them as having focus, under the condition that the box is checked.

option-background-intermediate-disabled
     The background colour for the box on disabled checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked.

option-foreground-intermediate-disabled
     The colour on text for disabled checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked.

option-aura-intermediate-disabled
     The colour of the aura around disabled checkboxes and radioboxes to mark them as having focus, under the condition that the box is in intermediate mode, that is, paritally checked.

option-background-change
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is not checked but is being clicked.

option-foreground-change
     The colour on text for checkboxes and radioboxes, under the condition that the box is not checked but is being clicked.

option-aura-change
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is not checked but is being clicked.

option-background-active-change
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is checked and is being clicked.

option-foreground-active-change
     The colour on text for checkboxes and radioboxes, under the condition that the box is checked and is being clicked.

option-aura-active-change
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is checked and is being clicked.

option-background-intermediate-change
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked and is being clicked.

option-foreground-intermediate-change
     The colour on text for checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked, and is being clicked.

option-aura-intermediate-change
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is in intermediate mode, that is, paritally checked and is being clicked.

option-background-hover-change
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is not checked but is being hovered and clicked.

option-foreground-hover-change
     The colour on text for checkboxes and radioboxes, under the condition that the box is not checked but is being hovered and clicked.

option-aura-hover-change
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is not checked but is being hovered and clicked.

option-background-active-hover-change
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is checked and is being hovered and clicked.

option-foreground-active-hover-change
     The colour on text for checkboxes and radioboxes, under the condition that the box is checked and is being hovered and clicked.

option-aura-active-hover-change
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is checked and is being hovered and clicked.

option-background-intermediate-hover-change
     The background colour for the box on checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked and is being hovered and clicked.

option-foreground-intermediate-hover-change
     The colour on text for checkboxes and radioboxes, under the condition that the box is in intermediate mode, that is, paritally checked, and is being hovered and clicked.

option-aura-intermediate-hover-change
     The colour of the aura around checkboxes and radioboxes to mark them as having focus, under the condition that the box is in intermediate mode, that is, paritally checked and is being hovered and clicked.

tabpane-background
     Background overriding window-background inside tabpanes.

tabpane-frame
     The colour on tabpane frames.

tabgroup-background
     The colour on the background on tab groups.

tabgroup-background-hover
     The colour on the background on tab groups, for hovered groups.

tab-background
     The background colour on tabs.

tab-foreground
     The colour on text on tabs.

tab-head
     The colour of a the head on tabs.

tab-background-active
     The background colour on active tabs.

tab-foreground-active
     The colour on text on active tabs.

tab-head-active
     The colour of a the head on active tabs.

tab-background-hover
     The background colour on hovered tabs.

tab-foreground-hover
     The colour on text on hovered tabs.

tab-head-hover
     The colour of a the head on hovered tabs.

tab-background-active-hover
     The background colour on active and hovered tabs.

tab-foreground-active-hover
     The colour on text on active and hovered tabs.

tab-head-active-hover
     The colour of a the head on active and hovered tabs.

slider-background
     The background colour in sliders.

slider-selected
     The background colour in sliders, marking the area that is selected.

slider-unselected
     The background colour in sliders, marking the area that is not selected.

slider-foreground
     The colour on text over sliders indicating the current value.

slider-knob
     The colour of the knob used to change the value on sliders.

slider-aura
     The colour of the aura around knob, used to change the value on sliders, marking the slider as having focus.

slider-stop
     The colour of the stop lines for sliders.

slider-background-hover
     The background colour in sliders, under the condition that the slider is being hovered.

slider-selected-hover
     The background colour in sliders, marking the area that is selected, under the condition that the slider is being hovered.

slider-unselected-hover
     The background colour in sliders, marking the area that is not selected, under the condition that the slider is being hovered.

slider-foreground-hover
     The colour on text over sliders indicating the current value, under the condition that the slider is being hovered.

slider-knob-hover
     The colour of the knob used to change the value on sliders, under the condition that the slider is being hovered.

slider-aura-hover
     The colour of the aura around knob, used to change the value on sliders, marking the slider as having focus, under the condition that the slider is being hovered.

slider-stop-hover
     The colour of the stop lines for sliders, under the condition that the slider is being hovered.

slider-background-hover-selected
     The background colour in sliders, under the condition that the slider is being hovered on the side of the slider that marks the selection.

slider-selected-hover-selected
     The background colour in sliders, marking the area that is selected, under the condition that the slider is being hovered on the side of the slider that marks the selection.

slider-unselected-hover-selected
     The background colour in sliders, marking the area that is not selected, under the condition that the slider is being hovered on the side of the slider that marks the selection.

slider-foreground-hover-selected
     The colour on text over sliders indicating the current value, under the condition that the slider is being hovered on the side of the slider that marks the selection.

slider-knob-hover-selected
     The colour of the knob used to change the value on sliders, under the condition that the slider is being hovered on the side of the slider that marks the selection.

slider-aura-hover-selected
     The colour of the aura around knob, used to change the value on sliders, marking the slider as having focus, under the condition that the slider is being hovered on the side of the slider that marks the selection.

slider-stop-hover-selected
     The colour of the stop lines for sliders, under the condition that the slider is being hovered on the side of the slider that marks the selection.

slider-background-hover-unselected
     The background colour in sliders, under the condition that the slider is being hovered on the side of the slider that does not mark the selection.

slider-selected-hover-unselected
     The background colour in sliders, marking the area that is selected, under the condition that the slider is being hovered on the side of the slider that does not mark the selection.

slider-unselected-hover-unselected
     The background colour in sliders, marking the area that is not selected, under the condition that the slider is being hovered on the side of the slider that does not mark the selection.

slider-foreground-hover-unselected
     The colour on text over sliders indicating the current value, under the condition that the slider is being hovered on the side of the slider that does not mark the selection.

slider-knob-hover-unselected
     The colour of the knob used to change the value on sliders, under the condition that the slider is being hovered on the side of the slider that does not mark the selection.

slider-aura-hover-unselected
     The colour of the aura around knob, used to change the value on sliders, marking the slider as having focus, under the condition that the slider is being hovered on the side of the slider that does not mark the selection.

slider-stop-hover-unselected
     The colour of the stop lines for sliders, under the condition that the slider is being hovered on the side of the slider that does not mark the selection.

slider-background-hold
     The background colour in sliders, under the condition that the slider is being pressed.

slider-selected-hold
     The background colour in sliders, marking the area that is selected, under the condition that the slider is being pressed.

slider-unselected-hold
     The background colour in sliders, marking the area that is not selected, under the condition that the slider is being pressed.

slider-foreground-hold
     The colour on text over sliders indicating the current value, under the condition that the slider is being pressed.

slider-knob-hold
     The colour of the knob used to change the value on sliders, under the condition that the slider is being pressed.

slider-aura-hold
     The colour of the aura around knob, used to change the value on sliders, marking the slider as having focus, under the condition that the slider is being pressed.

slider-stop-hold
     The colour of the stop lines for sliders, under the condition that the slider is being pressed.

slider-background-hold-selected
     The background colour in sliders, under the condition that the slider is being pressed on the side of the slider that marks the selection.

slider-selected-hold-selected
     The background colour in sliders, marking the area that is selected, under the condition that the slider is being pressed on the side of the slider that marks the selection.

slider-unselected-hold-selected
     The background colour in sliders, marking the area that is not selected, under the condition that the slider is being pressed on the side of the slider that marks the selection.

slider-foreground-hold-selected
     The colour on text over sliders indicating the current value, under the condition that the slider is being pressed on the side of the slider that marks the selection.

slider-knob-hold-selected
     The colour of the knob used to change the value on sliders, under the condition that the slider is being pressed on the side of the slider that marks the selection.

slider-aura-hold-selected
     The colour of the aura around knob, used to change the value on sliders, marking the slider as having focus, under the condition that the slider is being pressed on the side of the slider that marks the selection.

slider-stop-hold-selected
     The colour of the stop lines for sliders, under the condition that the slider is being pressed on the side of the slider that marks the selection.

slider-background-hold-unselected
     The background colour in sliders, under the condition that the slider is being pressed on the side of the slider that does not mark the selection.

slider-selected-hold-unselected
     The background colour in sliders, marking the area that is selected, under the condition that the slider is being pressed on the side of the slider that does not mark the selection.

slider-unselected-hold-unselected
     The background colour in sliders, marking the area that is not selected, under the condition that the slider is being pressed on the side of the slider that does not mark the selection.

slider-foreground-hold-unselected
     The colour on text over sliders indicating the current value, under the condition that the slider is being pressed on the side of the slider that does not mark the selection.

slider-knob-hold-unselected
     The colour of the knob used to change the value on sliders, under the condition that the slider is being pressed on the side of the slider that does not mark the selection.

slider-aura-hold-unselected
     The colour of the aura around knob, used to change the value on sliders, marking the slider as having focus, under the condition that the slider is being pressed on the side of the slider that does not mark the selection.

slider-stop-hold-unselected
     The colour of the stop lines for sliders, under the condition that the slider is being pressed on the side of the slider that does not mark the selection.

slider-background-disabled
     The background colour in disabled sliders.

slider-selected-disabled
     The background colour in disabled sliders, marking the area that is selected.

slider-unselected-disabled
     The background colour in disabled sliders, marking the area that is not selected.

slider-foreground-disabled
     The colour on text over disabled sliders indicating the current value.

slider-knob-disabled
     The colour of the knob used to change the value on disabled sliders.

slider-aura-disabled
     The colour of the aura around knob, used to change the value on disabled sliders, marking the slider as having focus.

slider-stop-disabled
     The colour of the stop lines for disabled sliders.

scroll-background
     The background colour on scrolls.

scroll-foreground
     The icon colour on buttons associated with scrolls.

scroll-knob
     The colour of the knob on scrolls.

scroll-button
     The background colour on buttons associated with scrolls.

scroll-background-hover
     The background colour on scrolls, under the condition that the area is being hovered.

scroll-foreground-hover
     The icon colour on buttons associated with scrolls, under the condition that the button is being hovered.

scroll-knob-hover
     The colour of the knob on scrolls, under the condition that the knob is being hovered.

scroll-button-hover
     The background colour on buttons associated with scrolls, under the condition that the button is being hovered.

scroll-background-hold
     The background colour on scrolls, under the condition that the area is being pressed.

scroll-foreground-hold
     The icon colour on buttons associated with scrolls, under the condition that the button is being pressed.

scroll-knob-hold
     The colour of the knob on scrolls, under the condition that the knob is being pressed.

scroll-button-hold
     The background colour on buttons associated with scrolls, under the condition that the button is being pressed.

scroll-background-disabled
     The background colour on scrolls, under the condition that the scroll is disabled.

scroll-foreground-disabled
     The icon colour on buttons associated with scrolls, under the condition that the button is disabled.

scroll-knob-disabled
     The colour of the knob on scrolls, under the condition that the scroll is disabled.

scroll-button-disabled
     The background colour on buttons associated with scrolls, under the condition that the button is disabled.

progress-background
     The background colour on progressbars.

progress-progress
     The colour of the bar, on progressbars, indicating how much progress has been made, or the colour of a marquee bar. This colour is usually blue, but sometimes green.

progress-good
     The colour of the bar, on progressbars, when the progressbar is used to indicate a state rather than a progress, and the state is considered good. This colour is usually green.

progress-normal
     The colour of the bar, on progressbars, when the progressbar is used to indicate a state rather than a progress, and the state is considered normal. This colour is usually yellow or green.

progress-bad
     The colour of the bar, on progressbars, when the progressbar is used to indicate a state rather than a progress, and the state is considered bad. This colour is usually orange or yellow.

progress-critical
     The colour of the bar, on progressbars, when the progressbar is used to indicate a state rather than a progress, and the state is considered critical. This colour is usually red.

progress-foreground
     The colour of text on progressbars, on the area that is not covered by a bar.

progress-foreground-progress
     The colour of text on progressbars, on the area that is covered by a bar indicating how much progress has been made or a marquee bar.

progress-foreground-good
     The colour of text on progressbars, on the area that is covered by a bar indicating a good state.

progress-foreground-normal
     The colour of text on progressbars, on the area that is covered by a bar indicating a normal state.

progress-foreground-bad
     The colour of text on progressbars, on the area that is covered by a bar indicating a bad state.

progress-foreground-critical
     The colour of text on progressbars, on the area that is covered by a bar indicating a critical state.

menu-background
     The background colour on menus and menu-items.

menu-foreground
     The colour on text on menus and menu-items.

menu-delimiter
     The colour on group-separation lines in menus.

menu-tear
     The colour on lines on menu-tearing menu-items.

menu-background-disabled
     The background colour on disabled menus and menu-items.

menu-foreground-disabled
     The colour on text on disabled menus and menu-items.

menu-tear-disabled
     The colour on lines on disabled menu-tearing menu-items.

menu-background-hover
     The background colour on menus and menu-items that are being hovered.

menu-foreground-hover
     The colour on text on menus and menu-items that are being hovered.

menu-tear-hover
     The colour on lines on menu-tearing menu-items.

menu-background-disabled-hover
     The background colour on disabled menus and menu-items that are being hovered.

menu-foreground-disabled-hover
     The colour on text on disabled menus and menu-items that are being hovered.

menu-tear-disabled-hover
     The colour on lines on disabled menu-tearing menu-items that are being hovered.

menu-background-open
     The background colour on menus and menu-items that are opened, that is submenus are visible.

menu-foreground-open
     The colour on text on menus and menu-items that are opened, that is submenus are visible.

toolbar-background
     The background colour on toolbars.

toolbar-foreground
     The colour on text on toolbars.

toolbar-delimiter
     The colour on group-separation lines in toolbars.

toolbar-handle
     The colour on the handle used to move toolbars.

tooltip-background
     The background colour on tooltips.

tooltip-foreground
     The colour on text on tooltips.

notification-background
     The background on notification.

notification-foreground
     The colour on text on notification.

notification-low
     Colour on notifications to indicate that they are of low priority. This colour is usually green or blue.

notification-normal
     Colour on notifications to indicate that they are of normal priority. This colour is usually blue or the same as notification-background.

notification-high
     Colour on notifications to indicate that they are of high priority. This colour is usually orange.

notification-critical
     Colour on notifications to indicate that they are of critical priority. This colour is usually red.

Nesting Applications
====================

Applications that want to embed another other application within it, should create a socket and start the other application with the environment variable MDS_EMBED set to the windows ID of the socket that the application should be embedded in.

All mds applications must be aware of the environment variable MDS_EMBED. The application may choose not to embed itself in the announced socket, however it should have good reason for not doing this.

All mds application must unset the environment variable MDS_EMBED before it starts any other program.

The Real Display Server
=======================

The environment variable PREFERRED_DISPLAY, should be set with the value mds, if and only if mds is started as a display server and not as a compatibility layer.

PREFERRED_DISPLAY is a space-separated (U+0020) list of supported display server protocol, ordered by preference.

If mds is started as a compatibility layer, mds should be added to PREFERRED_DISPLAY if and only if PREFERRED_DISPLAY lists any other display protocol.

If a compatibility server is successfully started, it shoul be listed in PREFERRED_DISPLAY. Be sure to keep the list ordered by preference.

mir
     Should be added if you are running a mir-to-mds server, like mds-mmds.

wayland
     Should be added if you are running a wayland-to-mds server, like mds-wmds.

x11
     Should be added if you are running an X-to-mds server, like mds-xmds.

New Concepts
************

Metadisplay Server
==================

A metadisplay server is a server that is connected to one or more display server's simultaneously. Additionally, it is acting as a display server on its own. Any server, or even client, running in this display will effectively be running in all of the displays connected to the metadisplay.

The idea of the metadisplay server came from the idea of letting the user have the clipboard shared across any number of selected display servers. Rather than having a clipboard server written specifically for this, it was seen as more appropriate to have a server than could let any server run inside any number of display server. Not only will this let the user run any server this way. It also makes it possible to run them across any number of computers.

If a hosting server, like mds-host, runs inside a metadisplay, any number of computers can connect to the metadisplay using a server like mds-remote. This creates a metadisplay with multiple display from multiple computers. If a clipboard server runs in this metadisplay, all of these display on all of these computers will share clipboard server.

Whilst not removing or degrading any functionality. A negative property of this setup it that it is centralised rather than distributed. If the computer hosting the metadisplay crashes, the other computers will no longer share this metadisplay, and lose the connection to any server running in it.

In addition to a the clipboard server, there is a host of other servers that makes sense to run in multiple displays or across multiple computer: drag-and-drop servers, human input device servers, output servers, and even windowing servers.

Endomonitor
===========

There are two forms of logical monitors: cineramas and endomonitor. A cinerama combines monitors into one monitor. Endomonitors takes a subset of a single monitor. Similar to having two monitors with overlaping output, (For example a monitor with mode--position 1600x1200+0+0 and a monitor with mode--position 1600x1200+800+600.) An endomonitor overlaps with another monitor, but only with that monitor and cannot be outside it even partially. But it does not need to cover it completely. This allows you to put a full-screen window on the endomonitor and thus only partially cover the physical monitor; for example keeping the clock visible.

Endomonitors do not need to be placed inside a physical monitor. They can be placed inside logical monitor too. Putting an endomonitor inside a cinerama lets you create a logical monitor that covers multiple monitors partially.

Discussion
**********

Server Architecture
===================

This chapter aims to enumerate advantages and disadvantages with micro-display servers, traditional monolithic display servers and other possible designs. Please chime in with any insight.

The Microserver Architecture
----------------------------

Description: The display server is implement with multiple binaries that speak with each other using a well defined protocol.

Implementations: mds.

Advantages:

  * Knowing the names of the servers you use and their purpose makes it very easy to find where you want to do patching in the source code.

  * Spaghetti code to a larger extent is virtually impossible; the microserver architecture guarantees a certain quality of the code architecture for the display server.

  * If the message passing used in the display server allows for message modification and retrieval ordering, extending, modifying and using the display server in unforeseen ways becomes much easier, and will often not require any modifications to the existing servers.

  * Replacing the display server is easier for a micro-display server than it is for a monolithic display server, because the servers could be replaced one by one and could even support running under two distinct protocol during the transitional period.

  * Not as many subprotocols needs to be defined. For example, recording the output of the display does not require a special protocol, one only needs to write a server that listens on messages passed between servers.

  * If a server crashes it does not crash the entire session. Crashes can most often be repaired.

  * Because servers can easily be omitted and replaced when starting the display server, it becomes much easier to mount the display server on top of an already running display server. For example, if you want the performance of weston but then flexibility and functionallity of mds, you could start mds inside weston and replace a small set of the servers with variants written to running on top of Wayland; of course with some functionallity of mds missing.

  * It is trivial to only have setuid on for the part of the display server where it is required.

The Monolithic Server Architecture
----------------------------------

Description: The display server is implemented as one binary.

Implementations: X11 (X11 is a protocol, I beleave all X11 servers are monolithic, atleast the major ones are), Mir, Wayland (Wayland is not actually monolithic, it is just a protocol. But Wayland is written with a monolithic mindset, and it is preferred that the display server implementation is monolithic.), Surface Flinger, Quartz Compositor, Desktop Window Manager.

Advantages:

  * The monolithic architecture makes it trivial to isolate information for clients to achieve confidentiality. Prioritising confidentiality however leads to problems implementing features such as screenshooting and global hotkeys.

  * Monolithic server does not need to pass messages between modules, but can rather perform normal function calls and achieve greater performance.

  * Monolithic display servers can have a smaller memory footprint than its full-fledged counterparts.

The Hybrid Server Architecture
------------------------------

Description: The display server is implemeneted with the microserver architecture except some components are built into the master server for performance or security reasons.

Hybrid display server could arguably be called milli-display servers (Playing of the International System of Units and its illogical prefix names.) to emphasis that they are small, but not as small as micro-display servers, are much more closely related to micro-display servers than monolithic display servers, and, in constrast with OS kernels, have a proper distinction from monolithic systems and microsystems.  (I don't know about calling them macro-display servers, that implies that they are the total opposite of micro-display servers, since ‘macro’ means large and ‘micro’ means small.)

Implementations: none?

Advantages:

  * Can achieve most of the microserver architecture's advantages, but not always to the same extent.

  * By integrating some servers into the master server, the hybrid architecture can isolate information for clients to achieve confidentiality. Prioritising confidentiality however leads to problems implementing features such as screenshooting and global hotkeys.

  * Large and high frequency messages does not need to be passed around to other servers if they are integrated into the master server. This lets hybrid display server achieve the same perfomance performance as monolithic display servers for tasks where it is desirable.

The mds protocol and its reference implemention can easily be made into a hybrid display server protocol and an implementation thereof.

The Megalithic Server Architecture
----------------------------------

Description: A monolithic display server where applications are loaded or compiled into the display server itself.

These are also known as mega-display servers.

Implementations: none?

Advantages:

  * No interprocess communication is required, apart from letting the display server know to load modules if it does not compile in its programs. This lets megalithic display server achieve even greater performance than monolithic display servers.

Disadvantages:

  * Imposes restrictions on which languages applications can use.

  * Imposes restrictions on how applications can behave.

  * Cannot be networked without exposing an alternative display server protocol.

  * The display becomes more crash prune; if an application crashes it is likely to crash the entire display.

  * Applications will run with the same privileges as the display server, which is root on most operating systems.

Megalithic display servers could be interesting for high-performing gaming consoles.

The Modular Server Architecture
-------------------------------

Description: A monolithic display server where server-like programs can be loaded as modules into the display server but applicates are connected with interprocess communication.

Implementations: none? (Desktop Window Manager is partially modular, but as of yet, this cannot be utilised by end-users.)

Advantages:

  * Can achieve that flexibility of micro-display servers, but not when networked, with the same memory footprint as monolithic display servers.

  * Has the same advantages as monolithic kernels.

  * Applications that require absolute performance can be loaded as modules and achieve the same performance as megalithic kernels, however with the same caveats.

With a little work the mds protocol could be transformed into a modular server display protocol, and with some work the reference implementation could be made into a modular server display.

The Modular Microserver Architecture
------------------------------------

Description: A modular display server with a module that enables clients to act as modules that communicates via interprocess communication rather than being loaded into the display server.

Implementations: none?

Advantages:

  * The modular microserver architecture seem to provide all of the advantages of the other architecture but none of the disadvantages. However, modules can still crash and bring down the display server, but the idea is to not load unstable modules but let the be servers. Therefore exo-diplay server are slightly more robust.

With a little work the mds protocol could be transformed into a modular server display protocol, and with some work the reference implementation could be made into a modular server display. Then the untransformed version of mds-server could be made into a module for the transformed version.

The Exoserver Architecture
--------------------------

Description: An exo-display server is a tiny display server that attempts to let applications access the underlaying system directly and implements basic interprocess communication to let applications share vital information and coordinate with each other.

Implementations: none?

Advantages:

  * Can achieve the same performance as megalithic display servers.

  * Can achieve the same robustness as micro-display servers.

Disadvantages:

  * Cannot be networked without exposing an alternative display server protocol.

Exo-display servers could be interesting for high-performing gaming consoles.

Fixing X.org Issues
===================

X.org is been critiqued for several shortcoming, some of which have caused people to start on new display servers to replace X.org. This chapter will list some issues and discuss how they can be avoided in mds.

Automatic Cleanup
-----------------

A common critique of X.org is that the monitor resolution is not restored if a game change the resolution and for some reason, for instance a software crash, does not switch back before exiting. This problem is not intrinsic to the protocol, but rather because of a lacking protocol. You can run a program like xrandr to change the monitor resolution for the entirety of the session and xrandr can exit when the resolution has changed. This is how it should be. However, there is no way to tell an X.org server to switch back if the connection between the program and server is lost. This is easily fixed by adding a lifespan parameter as found in set-gamma.

A similar critique of X.org is that gamma ramps are not restored when an application exits. Either the ones complaining about this do not understand why gamma ramps exists, namely so you can calibrate the monitor's output in respect to the colours, and just think it is a way to make the video in games brighter. Or they think we should have daemons running idly to have gamma adjustments. Or, more likely and more validly, its is poorly phrased and they actually want a way for applications, like games, to inform the display server to undo its modifications to the gamma ramps when the program exits. This is already supported by the mds protocol.

Input Problems
--------------

X11 allows programs to exclusively grab keyboard and mouse input. When a program that does this misbehaves or become unresponsive, you cannot do anything but manage it from another computer or restart the computer. In mds exclusively grabbing is achieved by setting the client priority for the related message to the highest priority.  (If multiple clients do this, it is arbitrary who gets the message first and can stop the others from getting it.) This is however not allowed (but nothing will stop you) as the idea is that clients should either select a predefined priority, select a priority between servers it to be between, or select a priority of 50 percent or 150 percent of another servers priority. Thus, unless a client breaks this rule, you can always have your server for switching to the TTY at a higher priority than other programs.

A similar, and probably related, problem in X.org is that global keybindings don't work when a popup or menu has focus. (Thankfully GTK+ will close that item if it receives unexpected input.) I have hard time seeing how this could become an issue in mds.

Another issue related to the keyboard in X.org is that hotkeys in programs do not work in a few situtations because the program was not designed with another keyboard layout in mind than the keyboard layout the developer used. I suggest that programs restrain themself from including Alternative Graph in their hotkeys and only use Shift for a through Z and Space. However, what I would really like to see is that toolkits lets users modify all hotkeys. If program additionally restrain themself to having all hotkeys contain control or alt the keyboard layouts with non-latin alphabets would not suffer because they do not use the latin alphabet.

Other Issues
------------

X11 display servers do not let you upgrade or otherwise replace graphics drivers online. Or other parts of it. X11 display servers could allow you to send a signal, for instance SIGUSR1, to upgrade the whole server, however this is not favourable, and X.org does not do this. The reference implemention of the mds protocol lets you safely upgrade any part of it online by sending SIGUSR1 to the server that should be upgraded. On catastrophic failure in this process the server would restart and lose volatile data, but the server should be upgraded and it would ask all running clients for resend information the server lost.

Another issue with X.org is that it is not multithreaded, which can cased intensive programs to freeze your desktop. mds is inherently pervasively parallel and only subsystems, rather than the whole system, can suffer from this. It is however easy for mds servers to implement pervasive threading, that is, letting each request spin up a new thread in the server.

Why Not Wayland
===============

Development of mds started out of concern that Wayland would not meet our needs, and the knowledge that X does not. We are now however aware that Wayland meets our needs even less than X. (Not even counting that the documentation for Wayland is way more lacking that X's documentation.)

Wayland only has protocols for drawing onto a buffer and input devices, and some very limited output protocols. Wayland is inherently inflexible. If anyone wants to add additional functionally, must do so in the compositor --- the window manager --- and publish the protocol. It is then up to all other compostors (window managers) to implement the protocol.

It should be noted that Wayland does not even have an official protocol for applying gamma corrects. Some compositors (window managers) choose to implement it by using colord.

Additionally, screenshooting, screen recording and global hotkeys must be implemented in the compositor (window manager). Why? Because of security. In Wayland, security always trumps useability and usefulness.

Another huge limitation of Wayland is that it does not have any network protocol. For it to be network, the compositor must implement a network protocol --- and there is no official network protocol. When this is all done, a compositor proxy must be written that can communicate with it.

Why Not Mir
===========

The major problem with Mir, and why we need mds instead, is that contributions to Mir are subject Canonical's contributions-limiting agreement (CLA).

Mir, like Wayland, is very limited. Mir is however easier to extend. Ignoring the CLA, Mir is better tham Wayland, but for similar reasons it is still not good enough.

Mir is however licensed under the GNU General Public License version 3 and GNU Lesser General Public License version 3. Much better than the MIT license, and hopefully we can steal some stuff.

Desktop Environments
====================

A design goal of mds is to bring unity to the graphical environment. Something desktop environments traditionally have been impairing. Traditionally a desktop environment would implement, or implement some of:

  * Window layout management (window manager)

  * Window decoration (window manager)

  * Workspaces (window manager)

  * Compositor (window manager)

  * Taskbars

  * Status icon trays

  * Launchers

  * Application menus

  * Autostart of applications

  * Keyboard bindings

  * Rat bindings

  * Rat barriers

  * Desktop

  * Widgets

  * Their own display manager (login screen)

  * Their own screensaver and screenlocker

  * Their own graphical toolkit

  * A bunch of random graphical tools

This is absolute madness, a waste of time and creates fragmentation.

There is no problem for a desktop environment development team to implement all this for their desktop environment for mds. However doing so is discourage for the mentioned reasons as well as because doing so means that the user needs to know what not to launch, that is, what the desktop environment will start.

Window Management
-----------------

For mds, a desktop environment should not have its own window layout manager. A better solution is to have a few well written window layout manager that are different from each other in how windows are layed out. These should not listen for keyboard actions to figure out how it shall rearrange the windows. Instead they should listen on the display server's messaging system for such commands, and mds-keybind or similar server should be configured with all hotkeys.

There are a few classes of window decorator. A desktop environment still do not need its own. They can however create themes for existing decorators. What we need here is a small set of window decorators that are very customisable.

Workspaces in X is poorly done. Window managers implement it, and pagers are window manager dependent (Well, there is Extended Window Manager Hints (EWMH), but it is very restricted.). Yet there are very few properties they can have:

  * Do workspaces span outputs, screens or the display?

  * Are workspaces dependent on outputs, screens or displays?

  * Do workspaces have a geometrical position?

  * Are new workspaces created when needed?

Clearly what we need is one workspace manager where these can be configured. And the desktop environments can create their own pagers if they see fit, but all pagers work everywhere.

Traditionally desktop environments wrote their own compositor for flash or otherwise fancy effects, or write a quirks to a common one so the common on could be used. With all other parts, of what has traditionally be the window manager, independent of the desktop environment, creating one universal compositor with plugin support for effects the desktop environment want to have, such be no problem.

Application Management
----------------------

Many X desktop environments provide taskbars, where all windows are listed. However because of Extended Window Manager Hints (EWMH), and the ability to read windows' position and wait for windows to move, this is not actually necessary. Of course, desktop environments may need to do this to theme the environment. A taskbar for mds should:

  * be about to restrict listed windows a those under specific outputs, and

  * be about to restrict listed windows to viewed workspaces.

Traditionally, status icon trays have been implemented with window embed method. And apart from there being two competing standard, this is pretty sane. But ther have been some restrictions mds does not suffer:

  * icons should not be rearranged, and

  * embedder did not know of the background looked where the icon was added.

Desktop environments should feel free to create their own themed application launchers and application menus. This functionally is already de facto standardised, and there is no reason to change anything.

Some desktop environments provide a method to for automatically starting applications during the startup of a desktop environment. This is discouraged. It is better to teach the user to edit ~/.mdsinitrc.

Input Management
----------------

Many desktop environments and window managers for X implement global keyboard bindings. This is not how you should do this. The servers should recognise commands passed via mds's interprocess communication. Configurations of the keyboard bindings should be done in a server like mds-keybind.

Similarily some desktop environments implement rat bindings (Notably hot corners.) and rat barriers. This too should be done via servers like like mds-ratbind and like mds-ratbarrier.

The Desktop
-----------

Desktop environments provide their own desktop because they want it to fit the rest of the environment. For example, it can use components of the desktop environment's file manager. This practice is however problematic, because they also implement the background, which is also implemented on top of the root windows. mds desktops should use a transparent background and let the root window be used for implementing the background.

Additionally, some desktop environments provide desktop widgets. These can either be drawn on the root window, the desktop window or as always-on-bottom windows. In mds, windows can have Z-order priority. That is, you can specify how important it is that your window is at the bottom or at the top. For widgets with input, it is recommended to use this to put the widget just above the desktop window. For windows without input, it is recommended draw on the root windows. However doing so requires that be listen for updates to the backgrund.

Why Dither Colours
==================

Now that almost all computers, and all modern computers, have support for 24-bit colour, colour dithering have faded to unexistence. The common logic is that the colours are good enough, or that we can only perceive 10 million colours, and 24-bit colour gives us almost 17 million colours. However, we can see the difference between two colours if they are next to each other and painted on large areas, even if the difference is the smallest that 24-bit colour can bring us.

So whilst 24-bit colour is good enough in most cases, it is not enough in gradients where the difference between the end colours are low, especially when these colours are bright. Therefore we still need dithering in some cases.

Now that we get increasingly higher pixel pitch our display output, dithering is going to look increasingly better.

Since we somehow got stuck at 24-bit colour, dithering is important.

GNU General Public License
**************************

     [file gpl.texinfo not included]

GNU Free Documentation License
******************************

     [file fdl.texinfo not included]