Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ryzhpolsos/redeye/llms.txt
Use this file to discover all available pages before exploring further.
RWML (RedEye Window Markup Language) is the XML-based declarative language that defines every visual element of the RedEye shell. You write RWML inside <layout> blocks and in any file imported from one, describing windows, the widgets inside them, shared variables, reusable attribute lists, templates, and inline C# scripts. RedEye parses RWML at startup and constructs live .NET Windows Forms objects from the descriptions.
The <layout> root element
All window definitions must live inside a <layout> element, either directly in config.xml or in a file imported from within <layout>:
<config>
<layout>
<!-- windows and layout-level directives go here -->
<import from="config/ui/taskbar.xml"/>
<import from="config/ui/desktop.xml"/>
</layout>
</config>
When RedEye loads configuration it calls ProcessNodes() on the layout node, which walks every child element and dispatches on its tag name. Special tags (variables, import, eval, script, etc.) are processed immediately and removed from the tree; <window> elements are passed to LayoutLoaderComponent.CreateWindowFromNode().
The <window> element
Each <window> element creates one shell window. All attributes are optional unless noted.
<window
id="taskbar"
x="${taskbar.margin}"
y="${taskbar.margin}"
width="${taskbar.width}"
height="${taskbar.height}"
type="shell"
border="none"
allowClose="false"
backgroundColor="${theme.color.background}">
<!-- widgets go here -->
</window>
Window attributes
| Attribute | Type | Default | Description |
|---|
id | string | "" | Unique identifier used by window.show(id), window.hide(id), and window.toggle(id) |
x | int | 0 | Left position in pixels |
y | int | 0 | Top position in pixels |
width | int | 0 | Width in pixels |
height | int | 0 | Height in pixels |
title | string | "" | Window title bar text |
type | enum | normal | Window Z-order and taskbar behavior (see below) |
border | enum | normal | Window border style (see below) |
backgroundColor | hex color | (none) | Background fill color, e.g. #13293d |
color | hex color | (none) | Foreground / text color |
autoShow | bool | true | Whether the window is visible on startup |
allowClose | bool | true | Whether clicking the close button hides the window |
allowRealClose | bool | false | Whether the window can actually be destroyed (vs. just hidden) |
minimizeButton | bool | true | Show the minimize button in the title bar |
maximizeButton | bool | true | Show the maximize button in the title bar |
transparent | bool | false | Mark the window surface as transparent |
allowTransparency | bool | false | Enable chroma-key transparency using ui.transparencyKey from core.xml |
opacity | float | 1.0 | Overall window opacity from 0.0 (invisible) to 1.0 (opaque) |
autoSize | bool | false | Let the window resize to fit its contents automatically |
padding | string | (none) | Inner padding, e.g. "8" or "8,4,8,4" (left,top,right,bottom) |
icon | string | (none) | Resource key for the window icon; empty string hides the icon |
onDeactivate | expression | (none) | Expression evaluated when the window loses focus |
Window types
The type attribute controls how the window behaves relative to other windows on the desktop:
| Value | Behavior |
|---|
normal | Standard application window; appears in the taskbar |
shell | Hidden from the taskbar and from the shell event listener; never receives WS_EX_TOOLWINDOW |
top | Stays above normal windows but below topMost; hidden from taskbar |
topMost | Always on top of all other windows; hidden from taskbar |
background | Locked to the bottom of the Z-order; used for the desktop wallpaper window |
Border styles
| Value | Behavior |
|---|
none | No border or title bar |
normal | Standard sizable border |
fixedDialog | Fixed-size dialog border |
fixedSingle | Fixed single-line border |
fixedToolWindow | Small title bar, no minimize/maximize |
sizableToolWindow | Sizable with a small title bar |
Window event handlers
Any attribute whose name starts with on is treated as an event handler. The value is an RWML expression that is evaluated when the event fires:
<window id="startMenu" onDeactivate="window.hide(startMenu)">
Common events mirror the underlying .NET Form events: Activate, Deactivate, Load, Shown, Resize, Click, etc. (prefix the event name with on, keeping the first letter lowercase).
Widget elements are the children of a <window>. RedEye maps each XML element name to a registered widget class via the plugin manager. The built-in widgets are:
| Element | Description |
|---|
<panel> | Container that can hold other widgets |
<label> | Static text display |
<button> | Clickable button |
<image> | Image display |
<textBox> | Editable text input |
<windowList> | Tracks and renders running application windows |
<appList> | Lists installed applications |
<tablePanel> | Grid-based layout container |
<flowPanel> | Flow-based layout container |
<webView> | Embedded web browser view |
<contextMenu> | Right-click context menu attached to another widget |
<externalProcess> | Embeds an external application window |
Widgets share a common set of base attributes defined in ShellWidgetConfig:
| Attribute | Type | Description |
|---|
id | string | Identifier for this widget |
x, y | int | Position relative to parent |
width, height | int | Size in pixels |
dock | string | Docking mode: fill, top, bottom, left, right |
anchor | string | Anchor edges when the parent is resized |
backgroundColor | hex | Background color |
color | hex | Foreground / text color |
font | string | Font name and size, e.g. "Segoe UI,10" |
padding | string | Inner padding |
margin | string | Outer margin |
layer | int | Z-order layer within the parent |
toolTip | string | Hover tooltip text |
updateInterval | int (ms) | Interval at which the widget re-evaluates dynamic attributes |
attrList | string | Name of an <attributeList> to apply as default attributes |
Taskbar example
The taskbar from config/ui/taskbar.xml shows a window containing a window list, an imported start button, and an inline <script> block:
<window
id="taskbar"
x="${taskbar.margin}"
y="${taskbar.margin}"
width="${taskbar.width}"
height="${taskbar.height}"
type="shell"
border="none"
allowClose="false"
backgroundColor="${theme.color.background}">
<import from="config/ui/startButton.xml"/>
<script>
<![CDATA[
using System.Diagnostics;
using System.Runtime.InteropServices;
static class NativeFunctions {
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, ref int lpdwProcessId);
}
// --main--
PluginManager.ExportFunction("killProcess", (args, _) => {
var hWnd = (IntPtr)long.Parse(args.ElementAt(0).ToString());
int pid = 0;
NativeFunctions.GetWindowThreadProcessId(hWnd, ref pid);
Process.GetProcessById(pid).Kill();
return string.Empty;
});
]]>
</script>
<windowList
x="${taskbar.item.size}"
y="0"
width="calc('${taskbar.width} - ${taskbar.tray.width} - ${taskbar.item.size}')"
height="${taskbar.height}">
<panel
width="${taskbar.item.size}"
height="${taskbar.item.size}"
margin="${theme.paddingMiddle},${theme.paddingMiddle},0,${theme.paddingMiddle}"
backgroundColor="if(${window.isActive}, ${theme.color.backgroundActive}, ${theme.color.backgroundChild})">
<image
id="icon"
src="${window.icon}"
dock="fill"
onClick="wapi.toggleWindow(${window.handle})"
toolTip="${window.title}"/>
<contextMenu for="icon">
<item action="wapi.closeWindow(${window.handle})">Close window</item>
<item action="killProcess(${window.handle})">Kill process</item>
</contextMenu>
</panel>
</windowList>
<import from="config/ui/tray.xml"/>
</window>
The start menu in config/ui/startMenu.xml demonstrates autoShow="false" and the onDeactivate event:
<window
id="startMenu"
x="${taskbar.margin}"
y="calc('${taskbar.margin} + ${taskbar.height}')"
width="${startMenu.width}"
height="${startMenu.height}"
type="topMost"
border="none"
backgroundColor="${theme.color.background}"
autoShow="false"
onDeactivate="window.hide(startMenu)">
<tablePanel dock="fill" rowCount="10" columnCount="2"
font="${theme.font.main}" color="${theme.font.color}">
<appList dock="fill" table.position="0,0" table.rowSpan="8" table.columnSpan="2">
<panel dock="fill" height="${startMenu.item.size}"
onClick="shellExecute(${app.command})">
<image src="${app.icon}" x="0" y="0"
width="${startMenu.item.size}" height="${startMenu.item.size}"/>
<label text="${app.name}"
x="${startMenu.item.size}" y="0"
width="calc('${startMenu.width} - ${startMenu.item.size}')"
height="${startMenu.item.size}" align="middleLeft"/>
</panel>
</appList>
<button attrList="flatButton" dock="fill" table.position="0,6"
text="Shutdown..." onClick="window.show(shutdownOptions)"/>
</tablePanel>
</window>
<import from="...">
The <import> element inlines another XML file at that position in the tree. It works anywhere inside <layout> or inside a <window>, and it causes RedEye to reload and re-process nodes starting from that point:
<layout>
<import from="config/ui/style/themedWindow.xml"/>
<import from="config/ui/desktop.xml"/>
</layout>
Imports are resolved relative to the RedEye application directory, not relative to the importing file. This means all paths are written from the application root regardless of nesting depth.
<variables> and <set>
A <variables> block defines one or more named values that can be referenced anywhere in the same node or its descendants:
<variables>
<set name="taskbar.height" value="66"/>
<set name="taskbar.width" value="calc('${screen.width} - 40')"/>
</variables>
Variables are scoped to the node tree — a variable set inside a <layout> is visible to all windows and widgets below it, but a variable set in a child node does not propagate upward.
Expression syntax
Attribute values and event handlers are run through the RWML expression parser before being used. The parser supports:
Variable substitution
Replaced with the current string value of the named variable at evaluation time:
<label text="${theme.font.color}"/>
Function calls
functionName(arg1, arg2, ...)
Functions are registered by core components and plugins. String literal arguments are wrapped in single quotes. Raw (un-quoted) identifiers are treated as variable lookups:
<set name="taskbar.width" value="calc('${screen.width} - 40')"/>
<image src="res.loadIcon(expand('%SYSTEMROOT%\System32\shell32.dll'), -171)"/>
Built-in expression functions
| Function | Description |
|---|
calc('expr') | Evaluates expr as an arithmetic expression and returns the result |
if(cond, then, else) | Returns then if cond is truthy, otherwise else |
ife(cond, then, else) | Like if, but then/else are themselves evaluated as RWML expressions |
expand('envStr') | Expands Windows environment variable references inside the string |
concat(a, b, ...) | Concatenates all arguments into a single string |
join(sep, a, b, ...) | Joins arguments with separator |
getvar('name') | Retrieves a variable value at expression evaluation time |
eq(a, b) | Returns "true" or "false" |
dateTime('format') | Current date/time formatted with a .NET format string |
guid() | Generates a new GUID string |
shellExecute(path, args?) | Launches a process |
shellExecuteHidden(path, args?) | Launches a process with no window |
window.show(id) | Shows a shell window by its id |
window.hide(id) | Hides a shell window by its id |
window.toggle(id) | Toggles a shell window’s visibility |
shell.restart() | Restarts the RedEye shell |
setWorkArea(x, y, w, h) | Tells Windows the usable desktop area |
res.loadImage(path, w?, h?) | Loads an image from disk and returns a resource key |
res.loadIcon(path, index) | Extracts an icon from a DLL and returns a resource key |
powerSearch.open() | Opens the PowerSearch launcher |
<eval> and <exec>
The <eval> and <exec> elements execute a single expression immediately during layout processing. They are equivalent:
<eval command="powerSearch.config(width, 600)"/>
<eval command="setWorkArea(${workArea.x}, ${workArea.y}, ${workArea.width}, ${workArea.height})"/>
The expression in command is evaluated using the same parser as attribute values. The return value is discarded.
<script> blocks
A <script> block executes arbitrary C# code (or another supported language) during layout processing. This is the primary extension point for defining custom functions that are then callable from RWML expressions:
<script>
<![CDATA[
using System.Diagnostics;
// --main-- marks the entry point for the script
PluginManager.ExportFunction("myFunc", (args, _) => {
return "hello from script";
});
]]>
</script>
The script runs with the following pre-bound variables in scope:
| Variable | Type | Description |
|---|
CurrentNode | ConfigNode | The RWML node that contains the <script> element |
ComponentManager | ComponentManager | Access to all RedEye components |
PluginManager | IPluginManager | Export and look up functions |
Config | IConfig | Access to the configuration tree |
| (other components) | Various | Each component is available by its interface name without the leading I |
The <script> element also supports a src attribute to load code from an external file:
<script src="config/scripts/myScript.cs"/>
And a language attribute to switch scripting languages (default is csharp):
<script language="csharp">
<![CDATA[ ... ]]>
</script>
<attributeList> and attrList
An <attributeList> defines a named bundle of attribute defaults that can be applied to any widget via the attrList attribute. This is the RWML equivalent of a CSS class:
<!-- Define the list (usually in an imported style file) -->
<attributeList name="flatButton">
<attribute name="border" value="none"/>
<attribute name="backgroundColor" value="${theme.color.backgroundChild}"/>
<attribute name="hoverColor" value="${theme.color.backgroundActive}"/>
</attributeList>
<!-- Apply it to a widget -->
<button attrList="flatButton" text="Lock" onClick="shellExecuteHidden('rundll32.exe', 'user32,LockWorkStation')"/>
Attributes from the list are only applied when the widget does not already define that attribute, so you can always override individual values directly on the element.
<if>, <then>, <else>
Conditional blocks let you include or exclude RWML nodes based on an expression:
<if condition="${someVariable}">
<then>
<label text="Variable is truthy"/>
</then>
<else>
<label text="Variable is falsy"/>
</else>
</if>
<defineTemplate> and <template>
Templates let you define a reusable subtree of widgets and stamp it out with different argument values:
<defineTemplate name="iconButton" arguments="btnIcon, btnAction">
<panel width="40" height="40">
<image src="${btnIcon}" dock="fill" onClick="${btnAction}"/>
</panel>
</defineTemplate>
<template name="iconButton" btnIcon="res.loadIcon(...)" btnAction="shellExecute('notepad.exe')"/>