Events
Caveat
If, from reading these notes, you conclude that I am off my rocker, you won’t be the first, and you may even be right.
No doubt there is a dozen and one reasons why none of this would ever work, but perhaps somewhere deep down there is a tiny fragment that could be used for something.
Contents
- Event models
- Targets
- Defined messages and events
Event models
Legacy Model
The Legacy Model comprises the UNIX streams of stdin, stdout and stderr, together with numeric signals. This is supported for ease of porting and even creating command-line utilities. The legacy model will deal with MDFS files using their canonical paths, just as they would any other available file system such as ext4 or FAT32.
The rest of this page describes the new Native Event Model.
Native Event Model
The Native Event Model is a structured message-passing system that permits all types of applications to send and receive detailed messages. This functions akin to both the Apple Event system and PowerShell, meaning that machine-readable commands and messages can be passed between any kind of application. Graphical applications will receive events from the window system (such as mouse clicks and window resize actions) as well as instructions from the user (such as opening files and launching URLs). Command-line tools can forward machine-readable data likewise.
Command-line and console applications use an event loop just the same as graphical applications. They are fundamentally identical to graphical applications; the application manifest will instruct the environment that the application expects a text console. Native Event Model applications will receive their input and send their output using messages, which programming language libraries will likely hide under traditional calls such as printf
and usage of traditional stream IDs.
Events are binary in nature and are structured roughly as follows:
- Source process ID
- Target process ID
- Event ID (system defined or custom)
- First parameter ID; null if no parameters
- Parameter length in bytes and/or pointer to the next parameter offset
- Parameter data
- Second parameter ID; null if no more parameters
- …
Marshalling of events (including retrieving a handle to a dedicated memory page) is handled within the language runtime.
Another approach:
- Source process ID
- Target process ID
- Event ID (system defined or custom)
- Message format
- Parameter count
- First parameter offset
- First parameter length
- Second parameter offset
- Second parameter length
- …
- First parameter data
- Second parameter data
- …
Here, each parameter’s identifying constant also equals its memory offset, e.g. PARAM_GENERAL_TARGET_HOST could be set to 0x00, indicating that the first parameter’s offset is at a memory location of the message page + header + 0 bytes. If the second parameter is then PARAM_GENERAL_CREDENTIALS, that would have a value 0x10, indicating that the offset is held 2 × 64-bits into the offset table. This requires an additional message format parameter to allow for the amount of initial general parameters to grow, e.g. adding an extra general parameter would require the offset address for the message-specific parameters to be increased by 16 bytes.
The first format is the most flexible, but it requires an iteration step to read off each parameter, identify it and assign it to a local variable:
nextParameterID := messageBlock~>[index];
index += 8;
while (nextParameterID != NULL) {
switch (messageBlock~>[index]) {
case PARAM_GENERAL_TARGET_HOST:
msg_targetHost := stringAt(messageBlock~>[index + 8], messageBlock~>[index + 4]);
case PARAM_GENERAL_ASYNC:
msg_runAsync := booleanAt(messageBlock~>[index + 8]);
}
index += 4;
}
The second format saves the iteration step as all the parameter offsets are known from the start.
For some activities, the easiest method is best. However, for high-performance events, a fast implementation is needed, both to encode and to decode messages. Depending on the language it may be possible to simply overlay a struct or object onto the message, although this will fail with variable length data unless a suitable compound record format is chosen. Depending on what language is chosen for application development, the structure of an object in memory could be made essentially identical to the message format, allowing the caller to simply pack an object and receive an object in response.
Targets
Each message is delivered to a single, specific target. Any broadcasting of messages is done by the system and not by the sender. The target can be another process or a system facility. System facilities may also be processes, but virtual targets remove the need to resolve the PID. The message can be delivered either to the local machine or to another computer via IP address, orthogonal to the target type: both processes and system facilities can be targeted on both localhost and any reachable network machine. Target selection including network targets is a universal facility that is not specific to any individual message or target. Network messages include the user’s session security information for authentication.
Command-line and console applications will served by a number of pseudo-targets: virtual process IDs that refer not to any specific process but instead to a pipeline peers. These are:
- VIRTUAL_PROC_UPSTREAM
- The upstream process in a text or data pipeline
- VIRTUAL_PROC_DOWNSTREAM
- A virtual receiving process that receives MESSAGE_SEND_TEXT messages, akin to stdout (if the target uses the Legacy Model, the payload text is converted to real stdin pipeline data on that process)
- VIRTUAL_PROC_ERROR_OUT
- A virtual receiving process that receives error messages via MESSAGE_SEND_TEXT, akin to stderr (if the target uses the Legacy Model, the payload text is converted to real stdin pipeline data on that process)
- VIRTUAL_PROC_DATA_IN
- A virtual sending process that generates data-transfer events
- VIRTUAL_PROC_DATA_OUT
- A virtual receiving process that receives MESSAGE_SEND_DATA messages (if the target uses the Legacy Model, the payload text is converted to plain text if possible, otherwise the message is rejected)
There are also global targets:
- VIRTUAL_PROC_SYSTEM
- Deliver a message to the operating system, and receive messages from the operating system (required privilege depends on the request)
- VIRTUAL_PROC_SESSION
- Deliver a message to a user’s session (requires administrator privilege if specifying a session other than the current user’s); the Session Manager handles this request
- VIRTUAL_PROC_DESKTOP
- Deliver a message to the user’s desktop environment, and receive messages from the operating system (requires administrator privilege if specifying a session other than the current user’s); the Desktop Manager handles this request
- VIRTUAL_PROC_WINDOWMGR
- Deliver a message to the Window Manager
- VIRTUAL_PROC_ALL_SESSION
- Broadcast a message to all processes within a user’s session (requires administrator privilege if specifying a session other than the current user’s)
- VIRTUAL_PROC_ALL
- Broadcast a message to all processes (requires administrator privilege)
Defined messages and events
As these notes originated in February 2019 (nearly four years ago) they are a little unclear, but it would appear that EVENT_* refers to an incoming event/request and MESSAGE_* refers to outgoing requests.
A sample of the possible messages and events is given below.
Default parameters applicable to all messages include:
Target host | The hostname or IP address of the host to which the message is to be sent (optional; defaults to localhost) |
---|---|
Credentials | A binary credentials token used to authenticate the request, either locally or on the remote host (optional; if omitted, the request operates under the security context of the caller) |
Run asynchronous | If specified, the message delivery request returns immediately with R_ASYNC_TOKEN and a token for identifying the response when it is ready |
Timeout | Fail the request with E_TIMEOUT after the specified time has elapsed; the receiving process may attempt to cancel the request but this is not guaranteed |
Some requests will fail if delivered to a remote system with optional parameters left unspecified, if the remote system is unable to assume a practical default.
Session Manager messages and events
The following events are sent to the Session Manager as VIRTUAL_PROC_SESSION.
MESSAGE_LOG_OFF
Instruct the Session Manager to log off the current user or (with administrator privileges) any user.
Session ID | The ID of the session to be logged out (optional; privileged; defaults to the current user on a local system, or the interactive session on a remote system) |
---|---|
Enforce | Prohibit R_REJECT; processes that reject the request will be terminated (optional; privileged) |
Time limit | How long the applications in the session are allowed to take to close before being terminated (optional; privileged) |
MESSAGE_LOCK
Instruct the Session Manager to lock the session for the current user or (with administrator privileges) any user.
Session ID | The ID of the session to be locked (optional; privileged; defaults to the current user on a local system, or the interactive session on a remote system) |
---|
MESSAGE_LIST_PROCESSES
Asks the Session Manager for a list of processes owned by the current user, visible to the current user or (with administrator privileges) all processes on the system. Returns details for the list processes requested. Fails if sent to a remote system without a specified session ID.
Session ID | The ID of the session to be queried (optional; privileged; defaults to the current user) |
---|
MESSAGE_END_PROCESS
Instruct the Session Manager to end the specified process by PID; administrator privileges are required if the process is outside of the user’s session. Parameter options include immediate termination, terminate after delay if the process does not exit, or return an error if the process remained running. Use MESSAGE_QUIT for a normal quit request for now.
Process ID | The ID of the process to be terminated (privileged if outside the current user’s session) |
---|
MESSAGE_LIST_SESSIONS
Asks the Session Manager for a list of logon sessions. Returns a list of sessions to the extent permitted by the user’s privileges.
Desktop Manager messages and events
The following events are sent to the Desktop Manager as VIRTUAL_PROC_DESKTOP. These message are available to both console and graphical applications, but console applications only have access to the Desktop Manager when they are running inside a graphical desktop session.
MESSAGE_LAUNCH
Launches all items specified within the message, which can be URLs, files and applications. Any required applications will be automatically launched if necessary.
The message can include a parameter indicating the desired action to be taken on each of the items, e.g. view, edit, print.
Items | A list of items to be launched |
---|---|
Action | The action to be taken: { view, edit, print, … } |
The choice of action may be used to determine which application handles the process, e.g. a user may have HTML pages set to be viewed in a browser and edited in a text editor (the print action would likely be sent to the browser rather than the text editor, but the file type can be set up to do either).
MESSAGE_OPEN_SYSTEM_CFG
Display the system configuration interface. Include a constant specifying the topic if desired. A 1:1 mapping between topics and settings panels is not guaranteed; the preferences application will show whatever panel contains the requested topic. This event is issued with no topic parameter when the user invokes a command in the desktop interface (e.g. Start → Settings) to request the settings interface. A standard system settings interface is included as standard but the user may rebind this to a program of their choice.
Window Manager messages and events
The following events are sent to the Window Manager as VIRTUAL_PROC_WINDOWMGR.
MESSAGE_SELECT_WINDOW
Window ID | The window to be selected |
---|---|
No raise | Select a window without raising it (potentially regulated as it could be used for focus theft keylogging) |
MESSAGE_CLOSE_WINDOW
Window ID | The window to be closed |
---|---|
Enforce | Prevent the application from rejecting the request with R_REJECT or R_DEFER if the window represents unsaved work; the application must take appropriate action (optional; privileged) |
Send a message for the receiving application to quit. The reason for this is included in the message body. This is a regulated message: sending processes may not deceive the receiving process about the nature of the request. Applications cannot presently offer a reason code.
Application messages and events
Each event delivered to a program generates a return record. The return record is headed by, and may solely comprise a response code. Response codes include R_RECEIVED and E_EVENT_NOT_APPLICABLE. Unidirectional messaging (as with pipeline applications) will never return data, but graphical applications may respond with reply data.
Events marked as mandatory must be handled by applications. All other events are situation-dependent, in that the application’s response depends on the reason for why it is unable to handle the event. Graphical applications receiving unwanted text events, and text applications receiving unwanted graphical events, should return E_EVENT_NOT_APPLICABLE.
At present, events are not explicitly grouped into any kind of classification, but this is not ruled out.
Some messages are regulated: the operating system verifies the honesty and integrity of the message before forwarding it.
MESSAGE_QUIT
Send a message for the receiving application to quit. The reason for this is included in the message body. This is a regulated message: sending processes may not deceive the receiving process about the nature of the request. Applications cannot presently offer a reason code.
EVENT_QUIT
The application is requested to close. The program can respond with R_REJECT to deny the request, or R_REPLY and a response message to handle other situations (yet to be formally defined), such as to request a delay and re-request, or to indicate how long it is likely to take to close.
The message will also indicate the reason for the request. Reasons include peer request (another process has issued MESSAGE_QUIT), user log off, system restart and system shutdown. Some situations such as an administrator shutdown request of a terminal server cannot be vetoed and will be marked as such: applications with open documents must take appropriate action such as taking an autosave and marking it for the user’s attention at next launch. Programs that veto mandatory quit messages or that ask for a delay (within a reasonable timescale) and outlive that delay will be killed.
This event is mandatory.
MESSAGE_SEND_TEXT
Send a string to another application. The target is expected to be able to receive text in some form: sending text to a graphical application is likely to fail with E_EVENT_NOT_APPLICABLE. The text must be UTF-8 format.
This is a regulated message: any payload data besides plain text is deleted, and the OS is free to reject the message outright instead for non-compliance. Applications receiving EVENT_RECEIVE_TEXT do not need to be concerned with stray data.
MESSAGE_SEND_ERROR
Send an error string to another application, in UTF-8 format. This is a regulated message: the recipient must be VIRTUAL_PROC_ERROR_OUT.
EVENT_RECEIVE_TEXT
Text has been received from (typically) an upstream pipeline process. The only payload of the message is plain UTF-8 text. A process should respond with E_EVENT_NOT_APPLICABLE if it has no use for this information, such as if it has been mistakenly targeted by a programmer or operator.
MESSAGE_WRITE_LOG
Report a message to the operating system. Send the message to VIRTUAL_PROC_SYSTEM. The message will be recorded automatically into the application’s log file.
MESSAGE_SEND_DATA
Send a generic data item (such as a string, object, array or map) to another application as part of a data pipeline. As with MESSAGE_SEND_TEXT, the target is expected to be able to receive data in this form. Legacy Model applications receiving such messages will receive the message as plain text if it can be converted, otherwise the message will be rejected by the operating system.
EVENT_RECEIVE_DATA
A generic data item has received from (typically) an upstream pipeline process. A process should respond with E_EVENT_NOT_APPLICABLE if it has no use for this information.
EVENT_FILE_RENAMED
A file has been renamed, re-tagged (MDFS) or moved (other file systems). The message body contains the file details, which are file system–dependent. The file handle ID is always passed, along with the new file path. For files that are now present on MDFS, the tag list and file ID are also included. Applications should update any user interface components that show the file’s details. These events are issued regardless of whether the application has registered to be notified about file activity.