aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2026-01-06 15:09:52 -0700
committerJosh Rahm <joshuarahm@gmail.com>2026-01-06 15:09:52 -0700
commit68dd63f6b3de774863051b66e609a0ca4f4ac2a1 (patch)
treea908ebced56be6fc14307b1a1dc304c47905f8e2
parent12f8ef6dbf8618aaa304d239fbfd3c1b7b4494d3 (diff)
downloadmontis-68dd63f6b3de774863051b66e609a0ca4f4ac2a1.tar.gz
montis-68dd63f6b3de774863051b66e609a0ca4f4ac2a1.tar.bz2
montis-68dd63f6b3de774863051b66e609a0ca4f4ac2a1.zip
[rebrand] to arken = runtime, montis = plugin
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt20
-rw-r--r--README.md133
-rw-r--r--arken/CMakeLists.txt (renamed from rt/CMakeLists.txt)12
-rw-r--r--arken/include/plugin.h (renamed from rt/include/plugin.h)0
-rw-r--r--arken/include/plugin_types.h (renamed from rt/include/plugin_types.h)0
-rw-r--r--arken/include/util.h (renamed from rt/include/util.h)0
-rw-r--r--arken/include/wl.h (renamed from rt/include/wl.h)0
-rw-r--r--arken/src/plugin.c (renamed from rt/src/plugin.c)0
-rw-r--r--arken/src/util.c (renamed from rt/src/util.c)0
-rw-r--r--arken/src/wl.c (renamed from rt/src/wl.c)0
-rw-r--r--arken/tools/genbuild.pl (renamed from rt/tools/genbuild.pl)0
-rw-r--r--arken/tools/genintf.pl (renamed from rt/tools/genintf.pl)0
-rw-r--r--montis/README.md (renamed from plug/README.md)0
-rw-r--r--montis/package.yaml (renamed from plug/package.yaml)2
-rw-r--r--montis/src/Config.hs (renamed from plug/src/Config.hs)0
-rw-r--r--montis/src/Link.hs (renamed from plug/src/Link.hs)0
-rw-r--r--montis/src/Montis/Base/Foreign/Runtime.hs (renamed from plug/src/Montis/Base/Foreign/Runtime.hs)0
-rw-r--r--montis/src/Montis/Base/Foreign/WlRoots.hs (renamed from plug/src/Montis/Base/Foreign/WlRoots.hs)0
-rw-r--r--montis/src/Montis/Base/Foreign/WlRoots/Types.hs (renamed from plug/src/Montis/Base/Foreign/WlRoots/Types.hs)0
-rw-r--r--montis/src/Montis/Core.hs (renamed from plug/src/Montis/Core.hs)0
-rw-r--r--montis/src/Montis/Core/Events.hs (renamed from plug/src/Montis/Core/Events.hs)0
-rw-r--r--montis/src/Montis/Core/Extensions.hs (renamed from plug/src/Montis/Core/Extensions.hs)0
-rw-r--r--montis/src/Montis/Core/Internal/Foreign/Export.hs (renamed from plug/src/Montis/Core/Internal/Foreign/Export.hs)0
-rw-r--r--montis/src/Montis/Core/Monad.hs (renamed from plug/src/Montis/Core/Monad.hs)0
-rw-r--r--montis/src/Montis/Core/Plugin/Interface.hs (renamed from plug/src/Montis/Core/Plugin/Interface.hs)0
-rw-r--r--montis/src/Montis/Core/Runtime.hs (renamed from plug/src/Montis/Core/Runtime.hs)0
-rw-r--r--montis/src/Montis/Core/Start.hs (renamed from plug/src/Montis/Core/Start.hs)0
-rw-r--r--montis/src/Montis/Core/State.hs (renamed from plug/src/Montis/Core/State.hs)0
-rw-r--r--montis/src/Montis/Core/State/Marshal.hs (renamed from plug/src/Montis/Core/State/Marshal.hs)0
-rw-r--r--montis/src/Montis/Foreign/Marshal.hs (renamed from plug/src/Montis/Foreign/Marshal.hs)0
-rw-r--r--montis/src/Montis/Standard/Drag.hs (renamed from plug/src/Montis/Standard/Drag.hs)0
-rw-r--r--montis/src/Montis/Standard/Keys.hs (renamed from plug/src/Montis/Standard/Keys.hs)0
-rw-r--r--montis/src/Montis/Standard/Mouse.hs (renamed from plug/src/Montis/Standard/Mouse.hs)0
-rw-r--r--montis/src/harness_adapter.c (renamed from plug/src/harness_adapter.c)0
-rw-r--r--montis/stack.yaml (renamed from plug/stack.yaml)0
-rw-r--r--montis/test/Spec.hs (renamed from plug/test/Spec.hs)0
37 files changed, 107 insertions, 62 deletions
diff --git a/.gitignore b/.gitignore
index fc1ccab..2eb9018 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-plug/.stack-work
+montis/.stack-work
*~
harness/build
wtr.so
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 18348ae..95296b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,32 +3,32 @@ project(montis LANGUAGES C)
add_custom_target(wlroots_build ALL DEPENDS "${WLROOTS_LIB_LINK}")
-add_subdirectory(rt)
-add_dependencies(montis wlroots_build)
+add_subdirectory(arken)
+add_dependencies(arken wlroots_build)
add_custom_target(
plug_build ALL
- COMMAND sh -c "if [ -d \"$1\" ] && [ ! -L \"$1\" ]; then rm -rf \"$2\"; mv \"$1\" \"$2\"; fi" sh "${CMAKE_SOURCE_DIR}/plug/.stack-work" "${CMAKE_BINARY_DIR}/stack-work"
+ COMMAND sh -c "if [ -d \"$1\" ] && [ ! -L \"$1\" ]; then rm -rf \"$2\"; mv \"$1\" \"$2\"; fi" sh "${CMAKE_SOURCE_DIR}/montis/.stack-work" "${CMAKE_BINARY_DIR}/stack-work"
COMMAND "${CMAKE_COMMAND}" -E make_directory "${CMAKE_BINARY_DIR}/stack-work"
- COMMAND "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_BINARY_DIR}/stack-work" "${CMAKE_SOURCE_DIR}/plug/.stack-work"
- COMMAND "${CMAKE_COMMAND}" -E chdir "${CMAKE_SOURCE_DIR}/plug" stack build
+ COMMAND "${CMAKE_COMMAND}" -E create_symlink "${CMAKE_BINARY_DIR}/stack-work" "${CMAKE_SOURCE_DIR}/montis/.stack-work"
+ COMMAND "${CMAKE_COMMAND}" -E chdir "${CMAKE_SOURCE_DIR}/montis" stack build
# Not sure why stack is generating an a.out file, but remove it.
- COMMAND "${CMAKE_COMMAND}" -E rm -f "${CMAKE_SOURCE_DIR}/plug/a.out"
- DEPENDS montis
+ COMMAND "${CMAKE_COMMAND}" -E rm -f "${CMAKE_SOURCE_DIR}/montis/a.out"
+ DEPENDS arken
COMMENT "Building Haskell plugin with Stack"
VERBATIM
)
add_custom_target(
run
- COMMAND sh -c "PLUGIN_SO=$(find '${CMAKE_BINARY_DIR}/stack-work' -name montis.so -type f | head -n 1); if [ -z \"$PLUGIN_SO\" ]; then echo 'montis.so not found in ${CMAKE_BINARY_DIR}/stack-work' 1>&2; exit 1; fi; \"$<TARGET_FILE:montis>\" -s foot -p \"$PLUGIN_SO\""
- DEPENDS montis plug_build
+ COMMAND sh -c "PLUGIN_SO=$(find '${CMAKE_BINARY_DIR}/stack-work' -name montis.so -type f | head -n 1); if [ -z \"$PLUGIN_SO\" ]; then echo 'montis.so not found in ${CMAKE_BINARY_DIR}/stack-work' 1>&2; exit 1; fi; \"$<TARGET_FILE:arken>\" -s foot -p \"$PLUGIN_SO\""
+ DEPENDS arken plug_build
USES_TERMINAL
VERBATIM
)
-install(TARGETS montis RUNTIME DESTINATION bin)
+install(TARGETS arken RUNTIME DESTINATION bin)
install(CODE [[
execute_process(
diff --git a/README.md b/README.md
index a7d3eeb..b722f5a 100644
--- a/README.md
+++ b/README.md
@@ -1,44 +1,89 @@
-# Wetterhorn
-
-Wetterhorn is a wlroots-based Wayland compositor inspired by XMonad. It has a
-unique harness-plugin architecture to support hot-reloading of some code. The
-goal is to have as much code as feasible hot-reloadable.
-
-This is accomplished by Wetterhorn's architecture. It has 2 parts:
-
- - A harness, written in C, that provides the core of interacting with Wayland.
- It is based off tinywl, dwl, weston and others. The window management and
- event handling duties are stubbed out though, relying on a plugin to manage
- those.
-
- - A plugin, written in Haskell, which provides the "configuration" for
- handling events and window management. This plugin could theoretically be
- replaced by any other program implementing the stubs.
-
- The aim is for the plugin to contain as much logic as possible as it is
- likely to be written in a safe language.
-
-This architecture provides some benefits.
-
- 1. It provides speed where it counts by having the compositor bits being
- written in a language like C.
-
- 2. It provides safety and expressiveness where it counts by having the logic
- and handlers written in a higher level language, like Haskell.
-
- 3. Right now the harness and Haskell plugin are coupled together, but in the
- future the boundary between the plugin and harness can be generalized to
- allow different plugins to be used if one particularly does not like the
- haskell implementation.
-
- 4. It enables hot-reloading. This is a huge benefit, and the main impetus for
- this architecture. With X11, the Window Manager was a separate binary that
- could be reloaded without killing the whole session. This is not the case
- for Wayland because the Window Manager and Compositor are the same binary.
- This is great for performance, but really bad for window managers like DWM
- and XMonad which rely on the hot-swappability as these WMs source code _is_
- their configuration.
-
- Now, when a changes is made to the plugin, it can be hot-reloaded by the
- harness, theoretically providing the best of both worlds in terms of
- performance and configuration expressiveness.
+
+```
+Ladies and Gentlemen, this is
+
+• ▌ ▄ ·. ▐ ▄ ▄▄▄▄▄▪ .▄▄ ·
+·██ ▐███▪▪ •█▌▐█•██ ██ ▐█ ▀.
+▐█ ▌▐▌▐█· ▄█▀▄ ▐█▐▐▌ ▐█.▪▐█·▄▀▀▀█▄
+██ ██▌▐█▌▐█▌.▐▌██▐█▌ ▐█▌·▐█▌▐█▄▪▐█
+▀▀ █▪▀▀▀ ▀█▄▀▪▀▀ █▪ ▀▀▀ ▀▀▀ ▀▀▀▀
+```
+
+Montis is a pluggable Wayland compositor, designed to make *hot-pluggable window
+management* a thing of the present ... again!
+
+
+## What Is It
+
+Montis is intentionally split into two components, each with a very different role.
+
+### Arken -- The Runtime
+
+**Arken** is the small, stable executable at the heart of the system. It very
+much *is* the compositor.
+
+* It is the compositor runtime.
+* It sets up wlroots, Wayland invariants, and lifecycle management.
+* It persists ocross reload.
+* It is deliberately lean: a harness, not an engine
+
+Arken exists to keep the window system alive while everything interesting
+changes around it.
+
+### Montis -- The Window Manager
+
+Montis is the window management logic, written in Haskell.
+
+* It compiles to a shared object (.so)
+* It is loaded into Arken at runtime
+* It can be edited, recompiled, and hot-reloaded on the fly
+* No compositor restart required
+
+Montis is not a DSL and not a configuration file. It is the window manager.
+Written in a Turing-complete programming language with full access to the Arken
+runtime and wlroots itself.
+
+### Why This is Powerful
+
+Montis takes direct inspiration from XMonad.
+
+XMonad is often described as a window manager “configured in Haskell”, but
+that’s misleading. In reality:
+
+* XMonad is a library
+* Your “configuration” is just a cleverly hidden main
+* You can rip the abstraction layer off entirely if you want
+* The configuration language is arbitrarily powerful
+
+That power is fundamentally impossible to replicate with window managers that
+invent their own configuration formats.
+
+However, XMonad has one major downside:
+
+ Because the configuration is the window manager, changing it requires a full
+ recompile—and a restart.
+
+On X11, that’s fine. The window manager is a separate process from the windowing
+system.
+
+On Wayland, that model collapses. The compositor is the window system.
+Restarting it kills every GUI application.
+
+### Montis's Mandate
+
+Montis exists to answer a simple question:
+
+ Can we get XMonad-style window management configuration on Wayland without
+ restarting the compositor?
+
+The constraints are strict:
+
+* Like XMonad, the configuration is the window manager
+* Changes must not require restarting the window system
+* No IPC-heavy control planes
+* No bespoke configuration languages
+
+The solution is a pluggable architecture:
+
+* A persistent runtime (Arken) that owns wlroots and the Wayland lifecycle
+* A hot-reloadable window manager (Montis) that owns behavior
diff --git a/rt/CMakeLists.txt b/arken/CMakeLists.txt
index 742d2f0..2bfd1d7 100644
--- a/rt/CMakeLists.txt
+++ b/arken/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.10)
project (
- montis
+ arken
VERSION 0.1
LANGUAGES C)
@@ -95,7 +95,7 @@ file (GLOB_RECURSE SOURCES src/*.c)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-add_executable (montis ${SOURCES} ${PLUGIN_LOAD} ${PLUGIN_INTF} ${WLROOTS_LIB_LINK}
+add_executable (arken ${SOURCES} ${PLUGIN_LOAD} ${PLUGIN_INTF} ${WLROOTS_LIB_LINK}
xdg-shell-protocol.c)
find_package(PkgConfig REQUIRED)
@@ -116,7 +116,7 @@ pkg_check_modules(WLREQ REQUIRED IMPORTED_TARGET
glesv2
)
-target_link_libraries(montis PRIVATE PkgConfig::WLREQ dl pthread ${WLROOTS_LIB_LINK})
+target_link_libraries(arken PRIVATE PkgConfig::WLREQ dl pthread ${WLROOTS_LIB_LINK})
pkg_check_modules(WLOPT IMPORTED_TARGET
cairo
@@ -141,9 +141,9 @@ pkg_check_modules(WLOPT IMPORTED_TARGET
)
if(WLOPT_FOUND)
- target_link_libraries(montis PRIVATE PkgConfig::WLOPT)
+ target_link_libraries(arken PRIVATE PkgConfig::WLOPT)
endif()
-target_link_directories(montis PUBLIC
+target_link_directories(arken PUBLIC
"${WLROOTS_BUILD_DIR}")
-target_link_options(montis PRIVATE -rdynamic)
+target_link_options(arken PRIVATE -rdynamic)
diff --git a/rt/include/plugin.h b/arken/include/plugin.h
index 3098602..3098602 100644
--- a/rt/include/plugin.h
+++ b/arken/include/plugin.h
diff --git a/rt/include/plugin_types.h b/arken/include/plugin_types.h
index df1eab5..df1eab5 100644
--- a/rt/include/plugin_types.h
+++ b/arken/include/plugin_types.h
diff --git a/rt/include/util.h b/arken/include/util.h
index 2ed2f70..2ed2f70 100644
--- a/rt/include/util.h
+++ b/arken/include/util.h
diff --git a/rt/include/wl.h b/arken/include/wl.h
index f10ee7d..f10ee7d 100644
--- a/rt/include/wl.h
+++ b/arken/include/wl.h
diff --git a/rt/src/plugin.c b/arken/src/plugin.c
index 3edf486..3edf486 100644
--- a/rt/src/plugin.c
+++ b/arken/src/plugin.c
diff --git a/rt/src/util.c b/arken/src/util.c
index e09cff9..e09cff9 100644
--- a/rt/src/util.c
+++ b/arken/src/util.c
diff --git a/rt/src/wl.c b/arken/src/wl.c
index 8963e39..8963e39 100644
--- a/rt/src/wl.c
+++ b/arken/src/wl.c
diff --git a/rt/tools/genbuild.pl b/arken/tools/genbuild.pl
index 1acabc0..1acabc0 100644
--- a/rt/tools/genbuild.pl
+++ b/arken/tools/genbuild.pl
diff --git a/rt/tools/genintf.pl b/arken/tools/genintf.pl
index 794f966..794f966 100644
--- a/rt/tools/genintf.pl
+++ b/arken/tools/genintf.pl
diff --git a/plug/README.md b/montis/README.md
index 5592f08..5592f08 100644
--- a/plug/README.md
+++ b/montis/README.md
diff --git a/plug/package.yaml b/montis/package.yaml
index bd42ced..c381197 100644
--- a/plug/package.yaml
+++ b/montis/package.yaml
@@ -70,7 +70,7 @@ executables:
- -O2
- -shared
- -I../build/
- - -I../rt/include/
+ - -I../arken/include/
- -I../build/wlroots/include
- -I../build/wlroots-src/include
- -DWLR_USE_UNSTABLE
diff --git a/plug/src/Config.hs b/montis/src/Config.hs
index 8ec06dd..8ec06dd 100644
--- a/plug/src/Config.hs
+++ b/montis/src/Config.hs
diff --git a/plug/src/Link.hs b/montis/src/Link.hs
index 4ac3f5c..4ac3f5c 100644
--- a/plug/src/Link.hs
+++ b/montis/src/Link.hs
diff --git a/plug/src/Montis/Base/Foreign/Runtime.hs b/montis/src/Montis/Base/Foreign/Runtime.hs
index 427545a..427545a 100644
--- a/plug/src/Montis/Base/Foreign/Runtime.hs
+++ b/montis/src/Montis/Base/Foreign/Runtime.hs
diff --git a/plug/src/Montis/Base/Foreign/WlRoots.hs b/montis/src/Montis/Base/Foreign/WlRoots.hs
index 272567f..272567f 100644
--- a/plug/src/Montis/Base/Foreign/WlRoots.hs
+++ b/montis/src/Montis/Base/Foreign/WlRoots.hs
diff --git a/plug/src/Montis/Base/Foreign/WlRoots/Types.hs b/montis/src/Montis/Base/Foreign/WlRoots/Types.hs
index c109653..c109653 100644
--- a/plug/src/Montis/Base/Foreign/WlRoots/Types.hs
+++ b/montis/src/Montis/Base/Foreign/WlRoots/Types.hs
diff --git a/plug/src/Montis/Core.hs b/montis/src/Montis/Core.hs
index 5399f1e..5399f1e 100644
--- a/plug/src/Montis/Core.hs
+++ b/montis/src/Montis/Core.hs
diff --git a/plug/src/Montis/Core/Events.hs b/montis/src/Montis/Core/Events.hs
index 91b8618..91b8618 100644
--- a/plug/src/Montis/Core/Events.hs
+++ b/montis/src/Montis/Core/Events.hs
diff --git a/plug/src/Montis/Core/Extensions.hs b/montis/src/Montis/Core/Extensions.hs
index 0e8384f..0e8384f 100644
--- a/plug/src/Montis/Core/Extensions.hs
+++ b/montis/src/Montis/Core/Extensions.hs
diff --git a/plug/src/Montis/Core/Internal/Foreign/Export.hs b/montis/src/Montis/Core/Internal/Foreign/Export.hs
index faa1964..faa1964 100644
--- a/plug/src/Montis/Core/Internal/Foreign/Export.hs
+++ b/montis/src/Montis/Core/Internal/Foreign/Export.hs
diff --git a/plug/src/Montis/Core/Monad.hs b/montis/src/Montis/Core/Monad.hs
index b7d1633..b7d1633 100644
--- a/plug/src/Montis/Core/Monad.hs
+++ b/montis/src/Montis/Core/Monad.hs
diff --git a/plug/src/Montis/Core/Plugin/Interface.hs b/montis/src/Montis/Core/Plugin/Interface.hs
index 73c0371..73c0371 100644
--- a/plug/src/Montis/Core/Plugin/Interface.hs
+++ b/montis/src/Montis/Core/Plugin/Interface.hs
diff --git a/plug/src/Montis/Core/Runtime.hs b/montis/src/Montis/Core/Runtime.hs
index 0d4c905..0d4c905 100644
--- a/plug/src/Montis/Core/Runtime.hs
+++ b/montis/src/Montis/Core/Runtime.hs
diff --git a/plug/src/Montis/Core/Start.hs b/montis/src/Montis/Core/Start.hs
index 54ec8c5..54ec8c5 100644
--- a/plug/src/Montis/Core/Start.hs
+++ b/montis/src/Montis/Core/Start.hs
diff --git a/plug/src/Montis/Core/State.hs b/montis/src/Montis/Core/State.hs
index ce8f903..ce8f903 100644
--- a/plug/src/Montis/Core/State.hs
+++ b/montis/src/Montis/Core/State.hs
diff --git a/plug/src/Montis/Core/State/Marshal.hs b/montis/src/Montis/Core/State/Marshal.hs
index 04a2a57..04a2a57 100644
--- a/plug/src/Montis/Core/State/Marshal.hs
+++ b/montis/src/Montis/Core/State/Marshal.hs
diff --git a/plug/src/Montis/Foreign/Marshal.hs b/montis/src/Montis/Foreign/Marshal.hs
index 157d928..157d928 100644
--- a/plug/src/Montis/Foreign/Marshal.hs
+++ b/montis/src/Montis/Foreign/Marshal.hs
diff --git a/plug/src/Montis/Standard/Drag.hs b/montis/src/Montis/Standard/Drag.hs
index a6ee878..a6ee878 100644
--- a/plug/src/Montis/Standard/Drag.hs
+++ b/montis/src/Montis/Standard/Drag.hs
diff --git a/plug/src/Montis/Standard/Keys.hs b/montis/src/Montis/Standard/Keys.hs
index 0b670eb..0b670eb 100644
--- a/plug/src/Montis/Standard/Keys.hs
+++ b/montis/src/Montis/Standard/Keys.hs
diff --git a/plug/src/Montis/Standard/Mouse.hs b/montis/src/Montis/Standard/Mouse.hs
index 933a2f4..933a2f4 100644
--- a/plug/src/Montis/Standard/Mouse.hs
+++ b/montis/src/Montis/Standard/Mouse.hs
diff --git a/plug/src/harness_adapter.c b/montis/src/harness_adapter.c
index db5e7ce..db5e7ce 100644
--- a/plug/src/harness_adapter.c
+++ b/montis/src/harness_adapter.c
diff --git a/plug/stack.yaml b/montis/stack.yaml
index 0faf47c..0faf47c 100644
--- a/plug/stack.yaml
+++ b/montis/stack.yaml
diff --git a/plug/test/Spec.hs b/montis/test/Spec.hs
index cd4753f..cd4753f 100644
--- a/plug/test/Spec.hs
+++ b/montis/test/Spec.hs