Files
ewwii/docs/book/config/configuration.html
2025-08-25 17:56:01 +05:30

356 lines
21 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE HTML>
<html lang="en" class="latte sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Configuration - Ewwii documentation</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="highlight-css" href="../highlight.css">
<link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
<link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href=".././theme/catppuccin.css">
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "../";
const default_light_theme = "latte";
const default_dark_theme = "macchiato";
window.path_to_searchindex_js = "../searchindex.js";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc.js"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('latte')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
sidebar_toggle.checked = false;
}
if (sidebar === 'visible') {
sidebar_toggle.checked = true;
} else {
html.classList.remove('sidebar-visible');
}
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="latte">Latte</button></li>
<li role="none"><button role="menuitem" class="theme" id="frappe">Frappé</button></li>
<li role="none"><button role="menuitem" class="theme" id="macchiato">Macchiato</button></li>
<li role="none"><button role="menuitem" class="theme" id="mocha">Mocha</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Ewwii documentation</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/Ewwii-sh/ewwii" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<div class="search-wrapper">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
<div class="spinner-wrapper">
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="writing-your-ewwii-configuration"><a class="header" href="#writing-your-ewwii-configuration">Writing your ewwii configuration</a></h1>
<p>(For a list of all built-in widgets (i.e. <code>box</code>, <code>label</code>, <code>button</code>), see <a href="../widgets/widgets.html">Widget Documentation</a>.)<br />
Ewwii is configured using its own language called <code>rhai</code>.
Using rhai, you declare the structure and content of your widgets, the geometry, position, and behavior of any windows,
as well as any state and data that will be used in your widgets.
Rhai is based around imparative syntax, which you may know from programming languages like C, Rust etc.
If you're using vim, you can make use of <a href="https://github.com/rhaiscript/vim-rhai">vim-rhai</a> for editor support.
If you're using VSCode, you can get syntax highlighting and formatting from <a href="https://marketplace.visualstudio.com/items?itemName=rhaiscript.vscode-rhai">vscode-rhai</a>.</p>
<p>Additionally, any styles are defined in CSS or SCSS (which is mostly just slightly improved CSS syntax).
While ewwii supports a significant portion of the CSS you know from the web,
not everything is supported, as ewwii relies on GTK's own CSS engine.
Notably, some animation features are unsupported,
as well as most layout-related CSS properties such as flexbox, <code>float</code>, absolute position or <code>width</code>/<code>height</code>.</p>
<p>To get started, you'll need to create two files: <code>ewwii.rhai</code> and <code>ewwii.scss</code> (or <code>ewwii.css</code>, if you prefer).
These files must be placed under <code>$XDG_CONFIG_HOME/ewwii</code> (this is most likely <code>~/.config/ewwii</code>).</p>
<p>Now that those files are created, you can start writing your first widget!</p>
<h2 id="creating-your-first-window"><a class="header" href="#creating-your-first-window">Creating your first window</a></h2>
<p>Firstly, you will need to create a top-level window. Here, you configure things such as the name, position, geometry, and content of your window.</p>
<p>Let's look at an example window definition:</p>
<pre><code class="language-rust ignore">enter([ // Add all defwindow inside enter. Enter is the root of the config.
defwindow("example", #{
monitor: 0,
windowtype: "dock",
stacking: "fg",
wm_ignore: false,
geometry: #{
x: "0%",
y: "2px",
width: "90%",
height: "30px",
anchor: "top center"
},
reserve: #{ distance: "40px" side: "top" }
}, label(#{ text: "example content" }))
])</code></pre>
<p>Here, we are defining a window named <code>example</code>, which we then define a set of properties for. Additionally, we set the content of the window to be the text <code>"example content"</code>.</p>
<p>You can now open your first window by running <code>ewwii open example</code>! Glorious!</p>
<h3 id="defwindow-properties"><a class="header" href="#defwindow-properties"><code>defwindow</code>-properties</a></h3>
<div class="table-wrapper"><table><thead><tr><th style="text-align: right">Property</th><th>Description</th></tr></thead><tbody>
<tr><td style="text-align: right"><code>monitor</code></td><td>Which monitor this window should be displayed on. See below for details.</td></tr>
<tr><td style="text-align: right"><code>geometry</code></td><td>Geometry of the window.</td></tr>
</tbody></table>
</div>
<p><strong><code>monitor</code>-property</strong></p>
<p>This field can be:</p>
<ul>
<li>the string <code>&lt;primary&gt;</code>, in which case ewwii tries to identify the primary display (which may fail, especially on wayland)</li>
<li>an integer, declaring the monitor index</li>
<li>the name of the monitor</li>
<li>a string containing a JSON-array of monitor matchers, such as: <code>'["&lt;primary&gt;", "HDMI-A-1", "PHL 345B1C", 0]'</code>. Ewwii will try to find a match in order, allowing you to specify fallbacks.</li>
</ul>
<p><strong><code>geometry</code>-properties</strong></p>
<div class="table-wrapper"><table><thead><tr><th style="text-align: right">Property</th><th>Description</th></tr></thead><tbody>
<tr><td style="text-align: right"><code>x</code>, <code>y</code></td><td>Position of the window. Values may be provided in <code>px</code> or <code>%</code>. Will be relative to <code>anchor</code>.</td></tr>
<tr><td style="text-align: right"><code>width</code>, <code>height</code></td><td>Width and height of the window. Values may be provided in <code>px</code> or <code>%</code>.</td></tr>
<tr><td style="text-align: right"><code>anchor</code></td><td>Anchor-point of the window. Either <code>center</code> or combinations of <code>top</code>, <code>center</code>, <code>bottom</code> and <code>left</code>, <code>center</code>, <code>right</code>.</td></tr>
<tr><td style="text-align: right"><code>resizable</code></td><td>Whether to allow resizing the window or not. Eiither <code>true</code> or <code>false</code>.</td></tr>
</tbody></table>
</div><br/>
Depending on if you are using X11 or Wayland, some additional properties exist:
<h4 id="x11"><a class="header" href="#x11">X11</a></h4>
<div class="table-wrapper"><table><thead><tr><th style="text-align: right">Property</th><th>Description</th></tr></thead><tbody>
<tr><td style="text-align: right"><code>stacking</code></td><td>Where the window should appear in the stack. Possible values: <code>fg</code>, <code>bg</code>.</td></tr>
<tr><td style="text-align: right"><code>wm_ignore</code></td><td>Whether the window manager should ignore this window. This is useful for dashboard-style widgets that don't need to interact with other windows at all. Note that this makes some of the other properties not have any effect. Either <code>true</code> or <code>false</code>.</td></tr>
<tr><td style="text-align: right"><code>reserve</code></td><td>Specify how the window manager should make space for your window. This is useful for bars, which should not overlap any other windows.</td></tr>
<tr><td style="text-align: right"><code>windowtype</code></td><td>Specify what type of window this is. This will be used by your window manager to determine how it should handle your window. Possible values: <code>normal</code>, <code>dock</code>, <code>toolbar</code>, <code>dialog</code>, <code>desktop</code>. Default: <code>dock</code> if <code>reserve</code> is specified, <code>normal</code> otherwise.</td></tr>
</tbody></table>
</div>
<h4 id="wayland"><a class="header" href="#wayland">Wayland</a></h4>
<div class="table-wrapper"><table><thead><tr><th style="text-align: right">Property</th><th>Description</th></tr></thead><tbody>
<tr><td style="text-align: right"><code>stacking</code></td><td>Where the window should appear in the stack. Possible values: <code>fg</code>, <code>bg</code>, <code>overlay</code>, <code>bottom</code>.</td></tr>
<tr><td style="text-align: right"><code>exclusive</code></td><td>Whether the compositor should reserve space for the window automatically. Either <code>true</code> or <code>false</code>. If <code>true</code> <code>:anchor</code> has to include <code>center</code>.</td></tr>
<tr><td style="text-align: right"><code>focusable</code></td><td>Whether the window should be able to be focused. This is necessary for any widgets that use the keyboard to work. Possible values: <code>none</code>, <code>exclusive</code> and <code>ondemand</code>.</td></tr>
<tr><td style="text-align: right"><code>namespace</code></td><td>Set the wayland layersurface namespace ewwii uses. Accepts a <code>string</code> value.</td></tr>
</tbody></table>
</div>
<h2 id="your-first-widget"><a class="header" href="#your-first-widget">Your first widget</a></h2>
<p>While our bar is already looking great, it's a bit boring. Thus, let's add some actual content!</p>
<pre><code class="language-rust ignore">fn greeter(name) {
return box(#{
orientation: "horizontal",
halign: "center"
}, [
button(#{ onclick: `notify-send 'Hello' 'Hello, ${name}'`, label: "Greet" })
]);
};</code></pre>
<p>To show this, let's replace the text in our window definition with a call to this new widget:</p>
<pre><code class="language-rust ignore">enter([
defwindow("example", #{
// ... properties omitted
}, greeter("Bob"))
])</code></pre>
<p>There is a lot going on here, so let's step through this.</p>
<p>We are creating a function named <code>greeter</code> and a function is equal to a component that returns a child (widget). So function has two uses: one to return a component, and the other to do a set of functions.
And this function takes one parameters, called <code>name</code>. The <code>name</code> parameter <em>must</em> be provided or else, you should emit it. Rhai does allow adding optional parameters, but we will talk about it later for the sake of beginners who are in-experienced with imprative programming languages.</p>
<p>Now inside the function, we declare the body of our widget that we are returning. We make use of a <code>box</code>, which we set a couple properties of.</p>
<p>We need this <code>box</code>, as a function can only ever contain a single widget - otherwise,
ewwii would not know if it should align them vertically or horizontally, how it should space them, and so on.
Thus, we wrap multiple children in a <code>box</code>.
This box then contains a button.
In that button's <code>onclick</code> property, we refer to the provided <code>name</code> using string-interpolation syntax: <code>`${name}`</code>. It is not possible to use a variable within a <code>""</code> or <code>''</code> just like javascript. You can learn more about it <a href="https://rhai.rs/book/ref/strings-chars.html?interpolation#string-interpolation">here</a>.</p>
<!-- TODO -->
<!-- In fact, there is a lot more you can do within `${...}` - more on that in the chapter about the [expression language](expression_language.md). -->
<p>To then use our widget, we call the function that provides the widget with the necessary parameters passed.</p>
<p>As you may have noticed, we are using a couple predefined widgets here. These are all listed and explained in the <a href="widgets.html">widgets chapter</a>.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../config/config_and_syntax.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../config/rendering_and_best_practices.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../config/config_and_syntax.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../config/rendering_and_best_practices.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<!-- Livereload script (if served using the cli tool) -->
<script>
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
<script src="../js/home_button.js"></script>
</div>
</body>
</html>