Repository navigation
Home
Medius is a high-performance tool designed to create surfaces (windows) on the shell layer of Wayland compositors. This document serves as the technical specification for configuration, layout logic, and widget behavior.
Medius windows are positioned relative to the output (screen) using the anchor property. The anchoring logic follows these rules:
-
Single Edge: (e.g.,
top) The surface is centered along that specific edge. -
Orthogonal Edges: (e.g.,
top left) The anchor point is the intersection of the two edges (the corner). - No Anchor: If no edges are specified, the surface is centered on the screen.
Compatibility Note: If your compositor does not support the
wlr-layer-shellprotocol, behavior is undefined; the surface will likely be rendered as a standard XDG window.
Medius uses the KDL document language for its configuration.
You can specify a configuration file via the --config or -c command-line flags. If these are absent, Medius defaults to searching for config.kdl, falling back to config.
If no absolute path is provided, Medius resolves the configuration file by searching these locations in order:
$MEDIUS_CONFIG_DIR$XDG_CONFIG_HOME/medius/$HOME/.config/medius/$HOME/medius//etc/xdg/medius/./resources/
Medius extends standard KDL functionality with the include key. This allows you to modularize your setup by importing other files into the main configuration.
- Includes can use absolute paths or filenames.
- Filenames are resolved using the Search Order defined above.
| Property | Default | Description |
|---|---|---|
| use_layer | normal |
Accepts normal, overlay, top, bottom, background. Specify which shell layer medius will reside. |
| anchor | none |
Accepts left, right, top, bottom. Combine two for corners. |
| rows | Required | Container for RowItems, stacked vertically. |
| width | 150 |
The minimum width (in pixels) requested from the compositor. |
| margin | 0 |
Space between the window edge and the anchored screen edge. |
| padding | 0 |
Internal spacing between window borders and content. |
| spacing | 0 |
Vertical space between stacked RowItem containers. |
| rounded_corner | 0 |
The default corner radius applied to all widgets. |
| animation_duration | 0 |
Speed (ms) for the ExpanderItem revealers. |
| close_timeout | -1 |
Milliseconds to wait before closing after mouse-out. -1 to disable. |
| close_on_escape | `` | If this property defined, medius will close on Escape keypress |
The RowItem is the primary layout component. While rows are stacked vertically, the widgets inside a specific RowItem are stacked horizontally (as columns). enabled property may be used to dynimacally show/hide this widget.
-
Revealer Management: Each RowItem manages a "revealer" container that houses all child
ExpanderItems. This is toggled via aButtonWidgetwith theexpanderproperty. -
CSS Customization: Every RowItem requires a
name. This name is appended to the widget's CSS class, allowing for granular styling.
rows {
network-row { // The RowItem name
button { ... } // Widgets are placed
slider { ... } // side-by-side
}
}-
Complete Property Descriptions:
Property Default Description enabled ""A shell command outputs to stdout. A return value of 0will hide this RowItem otherwise show this RowItem. It supports Dynamic Stateexpand ""If this property supplied, RowItem will take available space vertically. If multiple RowItem expanded, available space to expand shared equally between expanding RowItems. This property accepts centeredvalue which make the RowItem center aligned verticallyheight -1The minimum height (in pixels) requested for this row. rows ""RowItems may be nested, this property house child row item as if it is a widget (i.e. child rows stacked next to widgets). button ""Create a ButtonWidget.slider ""Create a SliderWidget.list ""Create a ListWidget.image ""Create an ImageWidget.textbox ""Create an TextboxWidget.
Widgets must be defined as children of either a RowItem or an ExpanderItem.
All widgets share common properties
| Property | Default | Description |
|---|---|---|
| label | "" |
Label text, which is positioned below the widget unless explicitly hidden by adding hidden keyword after label property name. This label also used to create CSS class for the widget |
| rotation | "normal" |
Possisble values are normal, left, right, upsidedown. This property will rotate widget's content accordingly |
| tooltip | "" |
A shell command outputs to stdout returning string to be used as tooltip when the wiget hovered by mouse pointer. This property may be formatted using Pango markup. It supports Dynamic State |
-
Behaviors:
- Acts as a standard button by default.
- Becomes a toggle button if both
on_click_onandon_click_offare defined. - Uses the XDG Icon Theme Specification. Setting an icon to
"none"hides it. - If button is a normal button,
icon_offis used. - On get state phase if state result is
0thenicon_offis used, otherwiseicon_onis used
-
Expander Integration: If the
expanderproperty is set, it creates a small>trigger button next to the main button to toggle visibility of associated items. See ExpanderItem. -
Complete Property Descriptions:
Property Default Description regenerate_list ""If this property set, after any on_click_*command, this widget will regenerate anyListWidgetsiblings it has.on_click_on ""A shell command to run when button is clicked; if button is a toggle button this command only run when button state is Active. on_click_off ""A shell command to run when toggle button is clicked and button state is Inactive. Note: if on_click_onabsent, this command will never run.expander Triggers parent revealer. See ExpanderItem. get_state - Expects output on stdout
- A value of
0makes button state Inactive if button is a toggle button and seticon_offas button icon - Otherwise make button state Active, if button is a toggle button and set
icon_onas button icon - Support Dynamic State
icon_on "none"Icon used when button state is Active; Supports Array Icon based on get_statevalueicon_off "none"Icon used when button state is Inactive or button is not toggle button icon_size 24The size in pixels to display icons at.
-
Behaviors:
- Displays an image using a "contain" fit (similar to CSS
object-fit: contain). - Supports both local absolute paths and remote URIs.
- Displays an image using a "contain" fit (similar to CSS
-
State Handling: The
get_statecommand should return a single string containing the URI or file to be displayed. -
Complete Property Descriptions:
Property Default Description get_state - Expects output on stdout
- An invalid URI renders nothing to image container
- Note this widget expects URI like file://[absolunt-path-to-a-file] for local files>
- Support Dynamic State
label ""Behaves differently from another wiget label property which is a static text, this is a shell command producing label to be displayed in the container. This maybe formatted inline using Pango markup. It supports Dynamic State on_click_on ""A shell command to run when button is clicked; if button is a toggle button this command only run when button state is Active. on_click_off ""A shell command to run when toggle button is clicked and button state is Inactive. Note: if on_click_onabsent, this command will never run.
-
Behaviors:
- Operates on an integer range defined by
range_lowandrange_high. -
Integrated Button: A ButtonWidget is automatically rendered alongside the slider if
on_click_onoron_click_offare supplied.
- Operates on an integer range defined by
-
Popover Integration: If a
popover_menunode is provided, a trigger button will appear to open a contextual menu. -
Complete Property Descriptions:
Property Default Description on_click_on ""Property to be passed onto slider's ButtonWidget.on_click_off ""Property to be passed onto slider's ButtonWidget.icon_on "none"Property to be passed onto slider's ButtonWidget. Icon rendered as regular image when neitheron_click_onnoron_click_offsuppliedicon_off "none"Property to be passed onto slider's ButtonWidget. Icon rendered as regular image when neitheron_click_onnoron_click_offsuppliedicon_size 24Property to be passed onto slider's ButtonWidget.button_get_state ""Property to be passed onto slider's ButtonWidgetas get_state.get_state ""A shell command returing Valuethis value is used as slider position; Support Dynamic Stateon_change ""A shell command to run when slider changed value. This command will be executed after slider has been stabilized to a value. This is a Parameterized commanad receiving slider's Valuerange_low 0Lowest Valuethis widget had.range_high 100Highest Valuethis widget had.popover_menu ""A KDL node to build a PopoverWidget.
-
Behaviors:
- Dynamically creates entries based on shell output.
- Each entry includes a state indicator:
✓for Active and-for Inactive.
-
Data Format: The
generatecommand must output one entry per line with three tab-separated fields:Value,Label, andState(where0is Inactive and1is Active). -
Complete Property Descriptions:
Property Default Description on_click_on ""A Parameterized Command that run when list clicked in Active state; Receiving Valueof corresponding list item. It may be markedregenerate_listresulting the list will be regenerated after click command finisheson_click_off ""A Parameterized Command that run when list clicked in Inactive state; Receiving Valueof corresponding list item. It may be markedregenerate_listresulting the list will be regenerated after click command finishesmax_height 600Maximum height in pixels this widget can expand to, if child widget takes more than this height a scrolled window will appear. hover_color #00000000RGBA hex color that used as item list background when hovered by mouse pointer. generate - Expects output on stdout
- Command must output one entry per line of three tab-separated fields:
Value,Label, andState
on_change ""A shell command to run when slider changed value. This command will be executed after slider has been stabilized to a value. This is a Parameterized commanad receiving slider's Valuerange_low 0Lowest Valuethis widget had.range_high 100Highest Valuethis widget had.popover_menu ""A KDL node to build a PopoverWidget.
-
Behaviors:
- Create a container for text.
- Text may be formatted inline using Pango markup.
- If
commandproperty supplied, this widget internally act as a button.
-
Complete Property Descriptions:
Property Default Description label ""Behaves differently from another wiget label property which is a static text, this is a shell command producing label to be displayed in the container. This maybe formatted inline using Pango markup. It supports Dynamic State command ""If this property set, this widget act like a button; Run this command when clicked
-
Behaviors:
- A child of a SliderWidget.
- Generates menu items only when the trigger button is clicked.
-
Data Format: The
generatecommand must return two tab-separated fields:ValueandLabel. -
Complete Property Descriptions:
Property Default Description on_click ""A Parameterized Command that run when a menu item clicked; Receiving Valueof corresponding menu itemgenerate - Expects output on stdout
- Command must output one entry per line of two tab-separated fields:
ValueandLabel
-
Behaviors:
- A child of a ButtonWidget that acts as a vertical container of [Widgets].
- Only one expander can be revealed within a single
RowItemat a time; opening one will automatically close others.
icon_on property may have node form instead of simple string value. In this form icon being used determined by some value, typically get_state return value. icon_on expects a value within range of 0..100 then medius will round up this number in scale of icon_on children count and select coresponding icon_on child index as icon.
Medius distinguishes between values that are set once and values that need to be updated in real-time. Properties supporting this (like get_state) accept two formats:
- Static State: A simple shell command string. It executes once during widget creation.
-
Dynamic State: A KDL node containing:
-
command: The shell command to run. -
interval: The time in seconds between each execution.
-
For interactive widgets (like Sliders or Lists), Medius needs to pass a value to your shell scripts. This is handled via a Token System:
- The Token: The first character of the command string is designated as the argument token.
- Replacement: Medius strips the first character and replaces every other occurrence of that token within the string with the actual value from the widget.
Example:
on_change "$ volume-control --set $"
If the slider value is 80, Medius will execute:
volume-control --set 80