<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Guile Swayer on Ozbem</title><link>https://www.ozbem.com/tags/software/guile-swayer/</link><description>Recent content in Guile Swayer on Ozbem</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>info@ozbem.com (ebeem)</managingEditor><webMaster>info@ozbem.com (ebeem)</webMaster><copyright>© 2026 ebeem</copyright><lastBuildDate>Tue, 31 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.ozbem.com/tags/software/guile-swayer/rss.xml" rel="self" type="application/rss+xml"/><item><title>Guile Swayer Introduction</title><link>https://www.ozbem.com/posts/software/guile-swayer/motivation/</link><pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate><author>info@ozbem.com (ebeem)</author><guid>https://www.ozbem.com/posts/software/guile-swayer/motivation/</guid><description>&#10;&lt;div id="outline-container-headline-1" class="outline-3"&gt;&#10;&lt;h3 id="headline-1"&gt;&#10;Guile Swayer&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;I am an &lt;code class="verbatim"&gt;Emacs&lt;/code&gt; user and previously used &lt;code class="verbatim"&gt;StumpWM&lt;/code&gt;, an &lt;code class="verbatim"&gt;X11&lt;/code&gt; window manager written in &lt;code class="verbatim"&gt;Common Lisp&lt;/code&gt;. I believe window managers should be scriptable because the level of workflow customization required by users often exceeds what can be achieved with simple configuration parameters (see my workflow below for a clearer understanding of why this is the case). Unfortunately, &lt;code class="verbatim"&gt;Sway/i3&lt;/code&gt; lacks a straightforward programmable interface for customization. This project provides complete control over &lt;code class="verbatim"&gt;Sway/i3&lt;/code&gt; using &lt;code class="verbatim"&gt;Guile&lt;/code&gt;! &lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-2" class="outline-3"&gt;&#10;&lt;h3 id="headline-2"&gt;&#10;Why Sway?&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-2" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;I had to migrate to &lt;code class="verbatim"&gt;Wayland&lt;/code&gt; at some point. Being a big fan of &lt;code class="verbatim"&gt;StumpWM&lt;/code&gt;, I tried to replicate a similar environment in one of the &lt;code class="verbatim"&gt;Wayland&lt;/code&gt; window managers. I made some progress with &lt;code class="verbatim"&gt;hyprland&lt;/code&gt; using a set of &lt;code class="verbatim"&gt;Guile&lt;/code&gt; bindings I developed called &lt;code class="verbatim"&gt;hypripc&lt;/code&gt;, but I found that &lt;code class="verbatim"&gt;Hyprland&lt;/code&gt; isn&amp;#39;t as stable as &lt;code class="verbatim"&gt;Sway&lt;/code&gt;.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-3" class="outline-3"&gt;&#10;&lt;h3 id="headline-3"&gt;&#10;Quick Test&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-3" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;Note: refer to the github wiki for more documentation.&lt;/p&gt;&#10;&lt;p&gt;&#10;After cloning this repository, you can immediately test it using the provided &lt;code class="verbatim"&gt;examples/playground/example.scm&lt;/code&gt; file in the directory, which demonstrates some of the features available in this package.&lt;/p&gt;&#10;&lt;p&gt;&#10;The &lt;code class="verbatim"&gt;examples/playground/example.scm&lt;/code&gt; file will:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Print the current focused workspace&lt;/li&gt;&#10;&lt;li&gt;Add a keybinding (Super+t) that launches Alacritty&lt;/li&gt;&#10;&lt;li&gt;Print a message when a workspace change event occurs&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;guile ./examples/playground/example.scm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-4" class="outline-3"&gt;&#10;&lt;h3 id="headline-4"&gt;&#10;Installation&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-4" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;All the examples included in this project reference the &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt; package relatively for ease of testing. To make &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt; package publicly visible to guile, it must be added to the &lt;code class="verbatim"&gt;GUILE_LOAD_PATH&lt;/code&gt; which should be &lt;code class="verbatim"&gt;/usr/local/share/guile/site/3.0&lt;/code&gt; for &lt;code class="verbatim"&gt;guile-3&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;&#10;If you use &lt;code class="verbatim"&gt;GUIX&lt;/code&gt;, you can simply install &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt; from the &lt;code class="verbatim"&gt;GUIX&lt;/code&gt; repository (thanks to @wrest64 [Alec Barreto]). If you are using another distro, you will have to ensure &lt;code class="verbatim"&gt;GUILE_LOAD_PATH&lt;/code&gt; points to correct path and execute the below commands to install &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt;&lt;/p&gt;&#10;&lt;div class="src src-bash"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; autoreconf -i&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ./configure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; make&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sudo make install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-5" class="outline-3"&gt;&#10;&lt;h3 id="headline-5"&gt;&#10;Quick Overview&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-5" class="outline-text-3"&gt;&#10;&lt;div id="outline-container-headline-6" class="outline-4"&gt;&#10;&lt;h4 id="headline-6"&gt;&#10;Query Sway&#10;&lt;/h4&gt;&#10;&lt;div id="outline-text-headline-6" class="outline-text-4"&gt;&#10;&lt;p&gt;&#10;You can retrieve information about &lt;code class="verbatim"&gt;Sway&lt;/code&gt;, such as list of available &lt;code class="verbatim"&gt;workspaces&lt;/code&gt; or &lt;code class="verbatim"&gt;outputs&lt;/code&gt;. The response will be in Guile records, which you can easily manipulate! (refer to &lt;code class="verbatim"&gt;swayipc/info.scm&lt;/code&gt;)&lt;/p&gt;&#10;&lt;div class="src src-scheme"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-scheme" data-lang="scheme"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; get focused workspace from a list of workspaces&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;focused-workspace-name&lt;/span&gt; &lt;span class="nv"&gt;workspaces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cond&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;null? &lt;/span&gt;&lt;span class="nv"&gt;workspaces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;#f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;equal? &lt;/span&gt;&lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-workspace-focused&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car &lt;/span&gt;&lt;span class="nv"&gt;workspaces&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-workspace-name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;car &lt;/span&gt;&lt;span class="nv"&gt;workspaces&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;else &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;focused-workspace-name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cdr &lt;/span&gt;&lt;span class="nv"&gt;workspaces&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;output record from function #sway-get-workspaces:\n ~a\n&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-get-workspaces&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;current focused workspace is [~a]\n&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;focused-workspace-name&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-get-workspaces&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;Note: To send commands to Sway, you must connect to the Sway sockets. Without connecting to the socket your commands won&amp;#39;t be sent to Sway. use the function &lt;code class="verbatim"&gt;(sway-connect-sockets!)&lt;/code&gt; immediately after the imports in your &lt;code class="verbatim"&gt;init.scm&lt;/code&gt; to ensure that the rest of the expressions can successfully send commands to Sway.&lt;/p&gt;&#10;&lt;div class="src src-scheme"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-scheme" data-lang="scheme"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; connect to sway sockets&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-connect-sockets!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-7" class="outline-4"&gt;&#10;&lt;h4 id="headline-7"&gt;&#10;Assign Keybindings&#10;&lt;/h4&gt;&#10;&lt;div id="outline-text-headline-7" class="outline-text-4"&gt;&#10;&lt;p&gt;&#10;You can assign keybindings that execute Guile code! Obviously, running shell commands is straightforward since you&amp;#39;re operating within Guile. Additionally, you have full access to Sway/i3 specific commands (refer to &lt;code class="verbatim"&gt;swayipc/dispatcher.scm&lt;/code&gt;).&lt;/p&gt;&#10;&lt;div class="src src-scheme"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-scheme" data-lang="scheme"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; normal sway keybindings (limited and can&amp;#39;t easily execute guile code)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-bindsym&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Mod4+t&amp;#34;&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;exec alacritty&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; general.scm interface for sway keybindings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; this uses sway-bindsym behind the scenes, but provides a much&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; user friendly interface to create complex keybindings structure&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; it also allows you to execute guile expressions on trigger.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; refer to modules/general.scm for more about how this is done.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; define leader keymap&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;execute given shell command&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;running: ~a\n&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt; &lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;general-define-keys&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:prefix&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;s-Space&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:wk&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Leader&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;o&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;rofi -show drun&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;C-g&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-mode&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:wk&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;abort&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; rofi keymap&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;general-define-keys&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:prefix&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;r&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:wk&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Rofi&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;p&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;~/.config/rofi/bin/password-manager&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;m&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;rofi-mount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;u&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;rofi-unmount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;w&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;.config/rofi/bin/wifi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;b&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;~/.config/rofi/bin/bluetooth&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;f&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;~/.config/rofi/bin/finder&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;k&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;~/.config/rofi/bin/keyboard-layout&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;P&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;~/.config/rofi/bin/powermenu&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;s&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;~/.config/rofi/bin/sound-input&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;S&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;~/.config/rofi/bin/sound-output&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; window management&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;general-define-keys&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:prefix&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;w&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="nv"&gt;:wk&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Window&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;v&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-layout&lt;/span&gt; &lt;span class="nv"&gt;SWAY-LAYOUT-SPLITV&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;h&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-layout&lt;/span&gt; &lt;span class="nv"&gt;SWAY-LAYOUT-SPLITH&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;f&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-fullscreen&lt;/span&gt; &lt;span class="nv"&gt;SWAY-FULLSCREEN-TOGGLE&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;d&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-layout&lt;/span&gt; &lt;span class="nv"&gt;SWAY-LAYOUT-DEFAULT&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;t&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-layout&lt;/span&gt; &lt;span class="nv"&gt;SWAY-LAYOUT-TABBED&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-8" class="outline-4"&gt;&#10;&lt;h4 id="headline-8"&gt;&#10;Subscribe to Events&#10;&lt;/h4&gt;&#10;&lt;div id="outline-text-headline-8" class="outline-text-4"&gt;&#10;&lt;p&gt;&#10;Certain scenarios necessitate subscribing to events. One example from my &lt;code class="verbatim"&gt;workflow&lt;/code&gt; described below requires this capability. With &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt;, you have the ability to listen for events and execute actions in response.&lt;/p&gt;&#10;&lt;div class="src src-scheme"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-scheme" data-lang="scheme"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; subscribe to events&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;workspace-changed&lt;/span&gt; &lt;span class="nv"&gt;workspace-event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let* &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;current-tree&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-workspace-event-current&lt;/span&gt; &lt;span class="nv"&gt;workspace-event&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;workspace&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-tree-name&lt;/span&gt; &lt;span class="nv"&gt;current-tree&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt; &lt;span class="no"&gt;#t&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;workspace changed to ~a!\n&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add-hook!&lt;/span&gt; &lt;span class="nv"&gt;sway-workspace-hook&lt;/span&gt; &lt;span class="nv"&gt;workspace-changed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;Note: To receive any events, you must subscribe to them. You can subscribe to individual events that interest you or to all available events. Without subscribing and running the event listener in your &lt;code class="verbatim"&gt;init.scm&lt;/code&gt;, your hooks will not receive any events.&lt;/p&gt;&#10;&lt;p&gt;&#10;The event listener thread is a Unix socket that waits for sway events. This must be executed, preferably as the last expression in your &lt;code class="verbatim"&gt;init.scm&lt;/code&gt; file, because &lt;code class="verbatim"&gt;thread-join&lt;/code&gt; will block execution. This blocking is necessary to keep the listener active and prevent the script from exiting.&lt;/p&gt;&#10;&lt;div class="src src-scheme"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-scheme" data-lang="scheme"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; subscribe to all events&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-subscribe-all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sway-start-event-listener-thread&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;thread-join!&lt;/span&gt; &lt;span class="nv"&gt;SWAY-LISTENER-THREAD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-9" class="outline-3"&gt;&#10;&lt;h3 id="headline-9"&gt;&#10;Documentation&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-9" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;Refer to the wiki for more information.&#10;Most of the source code is documented. You can refer to &lt;code class="verbatim"&gt;examples/stumpwm-like/init.scm&lt;/code&gt; for a complex stumpwm like configuration example. Here are some important points to consider before hacking your Sway setup&lt;/p&gt;&#10;&lt;div id="outline-container-headline-10" class="outline-4"&gt;&#10;&lt;h4 id="headline-10"&gt;&#10;Quick Start&#10;&lt;/h4&gt;&#10;&lt;div id="outline-text-headline-10" class="outline-text-4"&gt;&#10;&lt;p&gt;Clone this repository to your &lt;code class="verbatim"&gt;~/.config/sway&lt;/code&gt;&#10;It&amp;#39;s important to know where you clone the repo as you will have to reference it later by path to make a perfect setup.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-11" class="outline-4"&gt;&#10;&lt;h4 id="headline-11"&gt;&#10;Project Structure&#10;&lt;/h4&gt;&#10;&lt;div id="outline-text-headline-11" class="outline-text-4"&gt;&#10;&lt;div id="outline-container-headline-12" class="outline-5"&gt;&#10;&lt;h5 id="headline-12"&gt;&#10;Root Directory&#10;&lt;/h5&gt;&#10;&lt;div id="outline-text-headline-12" class="outline-text-5"&gt;&#10;&lt;table&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;File&lt;/td&gt;&#10;&lt;td&gt;Description&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;examples&lt;/td&gt;&#10;&lt;td&gt;Examples of configurations the you can refer to for inspiration&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;modules&lt;/td&gt;&#10;&lt;td&gt;Directory containing modules for extending Sway using &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt;.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;sjson&lt;/td&gt;&#10;&lt;td&gt;A patched version of &lt;code class="verbatim"&gt;guile-json&lt;/code&gt; (temporarily).&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;swayipc&lt;/td&gt;&#10;&lt;td&gt;Directory containing the core code for &lt;code class="verbatim"&gt;swayipc&lt;/code&gt;.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;README.org&lt;/td&gt;&#10;&lt;td&gt;This readme file&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-13" class="outline-5"&gt;&#10;&lt;h5 id="headline-13"&gt;&#10;guile-swayer Directory&#10;&lt;/h5&gt;&#10;&lt;div id="outline-text-headline-13" class="outline-text-5"&gt;&#10;&lt;table&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;File&lt;/td&gt;&#10;&lt;td&gt;Description&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;libs&lt;/td&gt;&#10;&lt;td&gt;Helpful libraries to help &lt;code class="verbatim"&gt;modules&lt;/code&gt; perform command sway &lt;code class="verbatim"&gt;tasks&lt;/code&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;modules&lt;/td&gt;&#10;&lt;td&gt;Directory containing modules for extending Sway using &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt;.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;sjson&lt;/td&gt;&#10;&lt;td&gt;A patched version of &lt;code class="verbatim"&gt;guile-json&lt;/code&gt; (temporarily).&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;swayipc&lt;/td&gt;&#10;&lt;td&gt;Directory containing the core code for &lt;code class="verbatim"&gt;swayipc&lt;/code&gt;.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-14" class="outline-5"&gt;&#10;&lt;h5 id="headline-14"&gt;&#10;guile-swayer/swayipc Directory&#10;&lt;/h5&gt;&#10;&lt;div id="outline-text-headline-14" class="outline-text-5"&gt;&#10;&lt;table&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;File&lt;/td&gt;&#10;&lt;td&gt;Description&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;connection&lt;/td&gt;&#10;&lt;td&gt;Establishes &lt;code class="verbatim"&gt;IPC&lt;/code&gt; connection for handling events and commands with Sway.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;dispatcher&lt;/td&gt;&#10;&lt;td&gt;Provides &lt;code class="verbatim"&gt;Guile functions&lt;/code&gt; for all available &lt;code class="verbatim"&gt;Sway&lt;/code&gt; commands.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;events&lt;/td&gt;&#10;&lt;td&gt;Provides &lt;code class="verbatim"&gt;Gulie Hooks&lt;/code&gt; for all available &lt;code class="verbatim"&gt;Sway&lt;/code&gt; events.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;info&lt;/td&gt;&#10;&lt;td&gt;Provides &lt;code class="verbatim"&gt;Guile functions&lt;/code&gt; for querying Sway&amp;#39;s current state and information.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;records&lt;/td&gt;&#10;&lt;td&gt;Provides &lt;code class="verbatim"&gt;Guile records&lt;/code&gt; representing Sway&amp;#39;s data structures.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-15" class="outline-5"&gt;&#10;&lt;h5 id="headline-15"&gt;&#10;guile-swayer/modules Directory&#10;&lt;/h5&gt;&#10;&lt;div id="outline-text-headline-15" class="outline-text-5"&gt;&#10;&lt;table&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;File&lt;/td&gt;&#10;&lt;td&gt;Description&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;auto-reload.scm&lt;/td&gt;&#10;&lt;td&gt;Watcher to automatically reload Sway when Guile files change.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;general.scm&lt;/td&gt;&#10;&lt;td&gt;Inspired by Emacs &lt;code class="verbatim"&gt;general&lt;/code&gt; package; provides an easy interface for keybindings.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;kbd.scm&lt;/td&gt;&#10;&lt;td&gt;Translates Emacs-like keybindings to be compatible with &lt;code class="verbatim"&gt;Sway&lt;/code&gt;.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;which-key.scm&lt;/td&gt;&#10;&lt;td&gt;Inspired by Emacs &lt;code class="verbatim"&gt;which-key&lt;/code&gt; package; enhances keybinding discovery.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;workspace-grid.scm&lt;/td&gt;&#10;&lt;td&gt;Configures workspaces in a grid (see workflow below).&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;workspace-groups.scm&lt;/td&gt;&#10;&lt;td&gt;Spans/synchronizes workspaces across monitors (see workflow below).&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&#10;1- You can start your &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt; configurations from the &lt;code class="verbatim"&gt;REPL&lt;/code&gt;, &lt;code class="verbatim"&gt;terminal&lt;/code&gt;, or a &lt;code class="verbatim"&gt;configuration file&lt;/code&gt;.&#10;Remember: for debugging or displaying output, it&amp;#39;s best to run Guile from the &lt;code class="verbatim"&gt;REPL&lt;/code&gt; or &lt;code class="verbatim"&gt;terminal&lt;/code&gt;. You can also pipe the output to a file if you desire.&lt;/p&gt;&#10;&lt;div class="src src-conf"&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code class="language-conf" data-lang="conf"&gt;# good idea to kill all current guile guile-swayer instances first&#10;exec_always &amp;#34;pkill -f &amp;#39;.*guile.*sway/init.scm&amp;#39;&amp;#34;&#10;&#10;# then run a fresh instance, sleeping ensures a more reilable execution&#10;exec_always &amp;#34;sleep 0.5 &amp;amp;&amp;amp; ~/.config/sway/init.scm&amp;#34;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;2- I plan to publish a module for &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt;, it&amp;#39;s currently not hosted anywhere. You&amp;#39;ll need to add the module to your &lt;code class="verbatim"&gt;load path&lt;/code&gt;. Additionally, &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt; includes another patched Guile library called &lt;code class="verbatim"&gt;guile-json&lt;/code&gt;, which is embedded for now. In the future, this will be included as a separate dependency rather than embedded.&lt;/p&gt;&#10;&lt;div class="src src-scheme"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-scheme" data-lang="scheme"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add-to-load-path&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;or &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;current-filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string-append &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;HOME&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/.config/sway/init.scm&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-16" class="outline-3"&gt;&#10;&lt;h3 id="headline-16"&gt;&#10;Workflow&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-16" class="outline-text-3"&gt;&#10;&lt;div id="outline-container-headline-17" class="outline-4"&gt;&#10;&lt;h4 id="headline-17"&gt;&#10;Workspace Grid&#10;&lt;/h4&gt;&#10;&lt;div id="outline-text-headline-17" class="outline-text-4"&gt;&#10;&lt;p&gt;&#10;I arrange my workspaces in a grid format. Typically, workspaces are laid out horizontally. With nine workspaces, navigating from workspace 1 to 9 using only horizontal directions can be cumbersome. Assigning a key to each workspace would be efficient but would clutter default mode keybindings. Some might create another mode or submap, but pressing multiple keys to move between workspaces becomes inefficient . I find the optimal solution is organizing workspaces in a grid format, enabling both horizontal and vertical navigation. Currently, I use a 3x3 grid with wraparound navigation.&lt;/p&gt;&#10;&lt;p&gt;&#10;Horizontal vs Grid 9 workspaces&lt;/p&gt;&#10;&lt;p&gt;&#10;Horizontal&lt;/p&gt;&#10;&lt;div class="src src-text"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1 2 3 4 5 6 7 8 9&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;Grid (3x3)&lt;/p&gt;&#10;&lt;div class="src src-text"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1 2 3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 4 5 6&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 7 8 9&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;Example navigation in a grid (&lt;code class="verbatim"&gt;cs#idx&lt;/code&gt; is current workspace):&lt;/p&gt;&#10;&lt;div class="src src-text"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cs#1&amp;gt; go right&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cs#2&amp;gt; go down&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cs#5&amp;gt; go down&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cs#8&amp;gt; go down (notice wraparound behavior)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cs#2&amp;gt; go right&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cs#3&amp;gt; ..&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;Note: this behavior is achieved via &lt;code class="verbatim"&gt;modules/workspace-grid.scm&lt;/code&gt; &lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-18" class="outline-4"&gt;&#10;&lt;h4 id="headline-18"&gt;&#10;Workspace Groups&#10;&lt;/h4&gt;&#10;&lt;div id="outline-text-headline-18" class="outline-text-4"&gt;&#10;&lt;p&gt;&#10;My workspaces function as groups or tasks that span across all three monitors in my setup. For example, if I switch to my &lt;code class="verbatim"&gt;communication&lt;/code&gt; workspace on one monitor, I want all monitors to switch to their respective &lt;code class="verbatim"&gt;communication&lt;/code&gt; workspaces. This means if I have WhatsApp on monitor #1, Discord on monitor #2, and IRC on monitor #3, they should all align to their designated communication workspace when I switch tasks.&lt;/p&gt;&#10;&lt;p&gt;&#10;Similarly, this setup extends to projects I work on. If I focus on my dotfiles, I want all monitors to switch to the workspace dedicated to that task. The same principle applies to game development or any other specific task or project workspace I engage with.&lt;/p&gt;&#10;&lt;p&gt;&#10;Normal workspaces&lt;/p&gt;&#10;&lt;div class="src src-text"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | ws#1 | ws#2 | ws#3 | ws#4 | ws#5 | ws#6 |&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;Grouped workspaces (3 monitors)&lt;/p&gt;&#10;&lt;div class="src src-text"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | ws#1 | ws#2 |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |-----------------------------------------------------|&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | ws#1-1 &amp;amp; ws#1-2 &amp;amp; ws#1-3 | ws#2-1 &amp;amp; ws#2-2 &amp;amp; ws#2-3 |&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;Example of navigation into a workspace (same behavior regardless of the method used to switch workspaces):&lt;/p&gt;&#10;&lt;div class="src src-text"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ws#1&amp;gt; go to ws#2-1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ws#2&amp;gt; go to ws#2-2 (same group, no switching)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ws#2&amp;gt; go to ws#1-3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ws#1&amp;gt; ..&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;You can partially configure workspace groups to span or sync only some workspaces. This allows you to have workspaces that do not span and others that do, with the ability to pin specific workspaces to their monitors when focused.&lt;/p&gt;&#10;&lt;p&gt;&#10;Note: this behavior is achieved via &lt;code class="verbatim"&gt;modules/workspace-groups.scm&lt;/code&gt; &lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-19" class="outline-4"&gt;&#10;&lt;h4 id="headline-19"&gt;&#10;Submaps and Which Key&#10;&lt;/h4&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-20" class="outline-3"&gt;&#10;&lt;h3 id="headline-20"&gt;&#10;which-key&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-20" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;&lt;code class="verbatim"&gt;which-key&lt;/code&gt; is a &lt;code class="verbatim"&gt;guile-swayer&lt;/code&gt; module that displays available key bindings in a pop-up window as you start typing a key sequence. This immediate feedback helps users discover and remember commands, reducing the need for memorization and speeding up the learning process. It improves workflow efficiency by allowing users to quickly access commands without interrupting their tasks. Additionally, &lt;code class="verbatim"&gt;which-key&lt;/code&gt; is highly customizable, supporting complex keymaps and personalized setups.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-21" class="outline-3"&gt;&#10;&lt;h3 id="headline-21"&gt;&#10;Submaps&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-21" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;Submaps are keymaps bound to specific prefix keys, grouping related commands under a common prefix. This logical grouping makes key bindings easier to remember and use while reducing conflicts by isolating namespaces for different command sets. Submaps support a hierarchical structure, which is scalable and modular, allowing users to expand and manage their configurations more effectively.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-22" class="outline-3"&gt;&#10;&lt;h3 id="headline-22"&gt;&#10;Combined Benefits&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-22" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;Together, &lt;code class="verbatim"&gt;which-key&lt;/code&gt; and submaps provide a powerful combination for managing key bindings. &lt;code class="verbatim"&gt;which-key&lt;/code&gt; enhances the discoverability of commands within submaps, helping users learn complex setups interactively. This combination reduces the memorization burden, streamlines workflows, and ensures an organized and efficient keybinding system in your sway setup.&lt;/p&gt;&#10;&lt;p&gt;&#10;&lt;img src="./imgs/which-key.gif" alt="./imgs/which-key.gif" title="./imgs/which-key.gif" /&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-23" class="outline-3"&gt;&#10;&lt;h3 id="headline-23"&gt;&#10;Layouts (experimental)&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-23" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;Layouts is a crucial feature of any tiling window manager. Sway, as a manual tiling window manager based on a tree structure, offers immense flexibility, theoretically allowing you to represent almost any layout you desire. However, the complexity of managing these layouts remains a challenge. Common layouts can make Sway much more user-friendly if they are easily toggled as needed. The goal of the layout feature in Guile Swayer is to provide these common layouts and make them easily togglable for specific workspaces. This feature is still very experimental and not yet intended for daily use.&lt;/p&gt;&#10;&lt;div id="outline-container-headline-24" class="outline-4"&gt;&#10;&lt;h4 id="headline-24"&gt;&#10;Planned layouts:&#10;&lt;/h4&gt;&#10;&lt;div id="outline-text-headline-24" class="outline-text-4"&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Alternating Layout&lt;/li&gt;&#10;&lt;li&gt;Emacs Layout&lt;/li&gt;&#10;&lt;li&gt;Xmonad&lt;/li&gt;&#10;&lt;li&gt;Matrix&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Example of alternating layout currently implemented.&#10;&lt;img src="./imgs/alternating-layout.gif" alt="./imgs/alternating-layout.gif" title="./imgs/alternating-layout.gif" /&gt;&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-25" class="outline-3"&gt;&#10;&lt;h3 id="headline-25"&gt;&#10;Change Logs&#10;&lt;/h3&gt;&#10;&lt;div id="outline-text-headline-25" class="outline-text-3"&gt;&#10;&lt;p&gt;&#10;V0.4.2&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;swayipc: improved the &lt;code&gt;sway-output&lt;/code&gt; function to accept output properties as parameters rather than a string&lt;/li&gt;&#10;&lt;li&gt;general: fixed issue #8, general doesn&amp;#39;t accept numeric values for keybindings&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;</description></item><item><title>I am leaving StumpWM and X11</title><link>https://www.ozbem.com/posts/software/guile-swayer/leaving-x11-and-stumpwm/</link><pubDate>Fri, 12 Apr 2024 00:00:00 +0000</pubDate><author>info@ozbem.com (ebeem)</author><guid>https://www.ozbem.com/posts/software/guile-swayer/leaving-x11-and-stumpwm/</guid><description>&#10;&lt;div id="outline-container-headline-1" class="outline-2"&gt;&#10;&lt;h2 id="headline-1"&gt;&#10;Lisp-Based Tools&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-1" class="outline-text-2"&gt;&#10;&lt;p&gt;If you have spent any significant time in the world of Lisp-based tools, you know that once you invest in tweaking them, you simply can&amp;#39;t quit. I have spent years living in &lt;code&gt;Emacs&lt;/code&gt; and &lt;code&gt;StumpWM&lt;/code&gt;, addicted to the idea that my environment shouldn&amp;#39;t just be &amp;#34;configurable,&amp;#34; but truly &lt;strong&gt;extensible&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;p&gt;&#10;In &lt;code&gt;StumpWM&lt;/code&gt; and &lt;code&gt;EXWM&lt;/code&gt;, the line between &amp;#34;user&amp;#34; and &amp;#34;developer&amp;#34; is paper-thin. If you want a new feature, you don’t submit a feature request; you open a REPL and redefine a function on the fly. However, with X11 nearing its end-of-life and the beauty of modern &lt;code&gt;Hyprland&lt;/code&gt; setups I am seeing, I feel it&amp;#39;s time to begin my transition to &lt;code&gt;Wayland&lt;/code&gt;.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-2" class="outline-2"&gt;&#10;&lt;h2 id="headline-2"&gt;&#10;Emacs as a Window Manager&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-2" class="outline-text-2"&gt;&#10;&lt;p&gt;I experimented with &lt;code&gt;EXWM&lt;/code&gt; (the Emacs X Window Manager), and initially, I was shocked, I couldn&amp;#39;t believe such a feat was even possible. But then again, it’s &lt;code&gt;Emacs&lt;/code&gt;; everything is possible. However, the experience highlighted a critical flaw: if Emacs froze or crashed, my entire session vanished. &lt;/p&gt;&#10;&lt;p&gt;&#10;I&amp;#39;ve come to realize that I don&amp;#39;t want to assign &lt;code&gt;Emacs&lt;/code&gt; heavy-duty system tasks like window management. I prefer using &lt;code&gt;Emacs&lt;/code&gt; as the interface between myself and other specialized utilities. Much like how &lt;code&gt;dired&lt;/code&gt; can act as a frontend for &lt;code&gt;ls&lt;/code&gt;, I believe a window manager should be assisted by a dedicated compositor written in a systems language like &lt;code&gt;C&lt;/code&gt;, &lt;code&gt;Rust&lt;/code&gt;, or &lt;code&gt;Zig&lt;/code&gt;. Entrusting the entire desktop session to a single-threaded Lisp interpreter is, in my view, a bottleneck for stability.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-3" class="outline-2"&gt;&#10;&lt;h2 id="headline-3"&gt;&#10;Creating a Lisp-Based Scripting Environment&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-3" class="outline-text-2"&gt;&#10;&lt;p&gt;I believe a window manager should apply the &amp;#34;Emacs Principle&amp;#34; because everyone&amp;#39;s workflow is unique. I have seen people using Emacs setups so personalized that I couldn&amp;#39;t even tell it was Emacs. &lt;/p&gt;&#10;&lt;p&gt;&#10;In my case, I have a specific workflow requirement: &lt;strong&gt;&lt;strong&gt;extending workspaces across multiple monitors&lt;/strong&gt;&lt;/strong&gt;. Assuming I have 2 monitors &lt;code&gt;ot#1&lt;/code&gt; and &lt;code&gt;ot#2&lt;/code&gt;. I want each to have its dedicated workspaces, let&amp;#39;s say each will have 3 workspaces. Whenever the workspace of &lt;code&gt;ot#1&lt;/code&gt; changes to workspace number 2, the workspace of &lt;code&gt;ot#2&lt;/code&gt; should also change to workspace number 2 (syncing).&lt;/p&gt;&#10;&lt;div class="src src-text"&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | ws#1 | ws#2 |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |-----------------------------------------------------|&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | ws#1-1 &amp;amp; ws#1-2 &amp;amp; ws#1-3 | ws#2-1 &amp;amp; ws#2-2 &amp;amp; ws#2-3 |&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&#10;I tried implementing this in &lt;code&gt;Sway&lt;/code&gt; and &lt;code&gt;Hyprland&lt;/code&gt; using their standard configuration languages, but I hit a wall. I could bind a key to switch multiple workspaces simultaneously, which worked temporarily, until a window stole focus or an unexpected workspace change occurred. This inevitably caused the monitors to get out of sync. &lt;/p&gt;&#10;&lt;p&gt;&#10;To solve this properly, I can&amp;#39;t just rely on simple keybindings; I need a persistent &lt;strong&gt;&lt;strong&gt;event listener&lt;/strong&gt;&lt;/strong&gt;. I need the environment to watch for workspace changes and programmatically sync the other monitors accordingly. This requires a level of logic that static config files simply cannot handle.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div id="outline-container-headline-4" class="outline-2"&gt;&#10;&lt;h2 id="headline-4"&gt;&#10;The Way Forward&#10;&lt;/h2&gt;&#10;&lt;div id="outline-text-headline-4" class="outline-text-2"&gt;&#10;&lt;p&gt;I need a compositor that is stable but provides a &amp;#34;hook&amp;#34; for high-level logic preferably with a lisp-based language like &lt;code&gt;guile&lt;/code&gt;. My next step is to experiment with a both &lt;code&gt;Sway&lt;/code&gt; and &lt;code&gt;Hyprland&lt;/code&gt; to see how far I can push the implementation of custom window management logic without sacrificing the stability of the underlying Wayland compositor.&lt;/p&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;</description></item></channel></rss>