diff options
| author | Josh Rahm <joshuarahm@gmail.com> | 2026-01-07 00:26:32 -0700 |
|---|---|---|
| committer | Josh Rahm <joshuarahm@gmail.com> | 2026-01-07 00:26:32 -0700 |
| commit | 4847aa0b4a6f945c24e1523e729652271bbc9680 (patch) | |
| tree | 9ffac8b1934153cbde6f6814277f80c337d937b1 | |
| parent | 37e5037b68fb35276f0c426779f61aa278d5b21b (diff) | |
| download | montis-4847aa0b4a6f945c24e1523e729652271bbc9680.tar.gz montis-4847aa0b4a6f945c24e1523e729652271bbc9680.tar.bz2 montis-4847aa0b4a6f945c24e1523e729652271bbc9680.zip | |
[rebrand] Arken -> Ark, Plugin -> Soul, Erebor -> Cross
36 files changed, 771 insertions, 854 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e191a24..b4921ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,43 +1,42 @@ cmake_minimum_required(VERSION 3.16) project(montis LANGUAGES C) -option(MONTIS_BUILD_BUNDLED_PLUGIN "Build the bundled Haskell plugin (montis.so)" ON) - -add_custom_target(wlroots_build ALL DEPENDS "${WLROOTS_LIB_LINK}") +option(MONTIS_BUILD_BUNDLED_SOUL "Build the bundled Haskell soul (montis.so)" ON) +if(DEFINED MONTIS_BUILD_BUNDLED_PLUGIN) + set(MONTIS_BUILD_BUNDLED_SOUL "${MONTIS_BUILD_BUNDLED_PLUGIN}") +endif() -add_subdirectory(arken) -add_dependencies(arken wlroots_build) +add_subdirectory(ark) -add_subdirectory(erebor) -add_dependencies(erebor wlroots_build) +add_subdirectory(cross) -if(MONTIS_BUILD_BUNDLED_PLUGIN) +if(MONTIS_BUILD_BUNDLED_SOUL) add_custom_target( - plug_build ALL + soul_build ALL 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}/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}/montis/a.out" - DEPENDS arken erebor - COMMENT "Building Haskell plugin with Stack" + DEPENDS ark cross + COMMENT "Building bundled Haskell soul 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:arken>\" -s foot -p \"$PLUGIN_SO\"" - DEPENDS arken plug_build + COMMAND sh -c "SOUL_SO=$(find '${CMAKE_BINARY_DIR}/stack-work' -name montis.so -type f | head -n 1); if [ -z \"$SOUL_SO\" ]; then echo 'montis.so not found in ${CMAKE_BINARY_DIR}/stack-work' 1>&2; exit 1; fi; \"$<TARGET_FILE:ark>\" -s foot -p \"$SOUL_SO\"" + DEPENDS ark soul_build USES_TERMINAL VERBATIM ) endif() -install(TARGETS arken RUNTIME DESTINATION bin) +install(TARGETS ark RUNTIME DESTINATION bin) -if(MONTIS_BUILD_BUNDLED_PLUGIN) +if(MONTIS_BUILD_BUNDLED_SOUL) install(CODE [[ execute_process( COMMAND sh -c "find '${CMAKE_BINARY_DIR}/stack-work' -name montis.so -type f | head -n 1" @@ -17,17 +17,17 @@ management* a thing of the present ... again! Montis is intentionally split into two components, each with a very different role. -### Arken -- The Runtime +### Ark -- The Runtime -**Arken** is the small, stable executable at the heart of the system. It very +**Ark** 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 persists across reload. * It is deliberately lean: a harness, not an engine -Arken exists to keep the window system alive while everything interesting +Ark exists to keep the window system alive while everything interesting changes around it. ### Montis -- The Window Manager @@ -35,23 +35,23 @@ changes around it. Montis is the window management logic, written in Haskell. * It compiles to a shared object (.so) -* It is loaded into Arken at runtime +* It is loaded into Ark 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 +Written in a Turing-complete programming language with full access to the Ark runtime and wlroots itself. -#### Erebor -- Native Bridge Library +#### Cross -- Native Bridge Library -**Erebor** (`liberebor.a`) is a static C library that contains the native -functions Montis uses to interact with Arken/wlroots. It is linked into the -`montis.so` plugin so these FFI bindings hot-reload along with the Haskell code +**Cross** (`libcross.a`) is a static C library that contains the native +functions Montis uses to interact with Ark/wlroots. It is linked into the +`montis.so` soul so these FFI bindings hot-reload along with the Haskell code instead of living inside the long-running compositor process. -Code lives in `erebor/src` and headers in `erebor/include` (notably -`erebor/include/util.h`). +Code lives in `cross/src` and headers in `cross/include` (notably +`cross/include/util.h`). ### Why This is Powerful @@ -95,7 +95,7 @@ The constraints are strict: The solution is a pluggable architecture: -* A persistent runtime (Arken) that owns wlroots and the Wayland lifecycle +* A persistent runtime (Ark) that owns wlroots and the Wayland lifecycle * A hot-reloadable window manager (Montis) that owns behavior ## Building @@ -109,24 +109,24 @@ The solution is a pluggable architecture: - `meson` (wlroots is built via Meson) and a backend like `ninja` - `wayland-scanner` and `wayland-protocols` - `curl` (first build downloads wlroots) -- Optional (only for the bundled plugin): Haskell toolchain via Stack: `stack` (+ GHC) +- Optional (only for the bundled soul): Haskell toolchain via Stack: `stack` (+ GHC) ### Build This repo uses CMake to build: -- `arken` (the compositor runtime) -- `erebor` (`liberebor.a`) -- the Haskell plugin (`montis.so`) via Stack +- `ark` (the compositor runtime) +- `cross` (`libcross.a`) +- the bundled Haskell soul (`montis.so`) via Stack ```sh cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug cmake --build build ``` -To build only the runtime + bridge library (no bundled plugin): +To build only the runtime + bridge library (no bundled soul): ```sh -cmake -S . -B build -DMONTIS_BUILD_BUNDLED_PLUGIN=OFF +cmake -S . -B build -DMONTIS_BUILD_BUNDLED_SOUL=OFF cmake --build build ``` @@ -136,21 +136,21 @@ To run via the CMake helper target: cmake --build build --target run ``` -Note: the `run` target currently starts `arken` with `-s foot`, so you’ll want +Note: the `run` target currently starts `ark` with `-s foot`, so you’ll want `foot` installed (or adjust the target in `CMakeLists.txt`). -### Using Your Own Plugin +### Using Your Own Soul -If you disable the bundled plugin (`-DMONTIS_BUILD_BUNDLED_PLUGIN=OFF`), you can -build and supply your own plugin `.so` at runtime. +If you disable the bundled soul (`-DMONTIS_BUILD_BUNDLED_SOUL=OFF`), you can +build and supply your own soul `.so` at runtime. -- Plugin ABI: `arken/include/plugin.h` (plugin header: `arken/include/plugin_interface.h`) -- Optional bridge helpers: `erebor/include` + `build/erebor/liberebor.a` +- Soul ABI: `ark/include/soul.h` (soul header: `ark/include/soul_interface.h`) +- Optional bridge helpers: `cross/include` + `build/cross/libcross.a` Runtime invocation looks like: ```sh -./build/arken/arken -p /path/to/your_plugin.so +./build/ark/ark -p /path/to/your_soul.so ``` ## Installing @@ -160,5 +160,5 @@ cmake --install build --prefix ~/.local ``` This installs: -- `arken` to `~/.local/bin` -- if `-DMONTIS_BUILD_BUNDLED_PLUGIN=ON`, the latest built plugin `.so` to `~/.local/lib` +- `ark` to `~/.local/bin` +- if `-DMONTIS_BUILD_BUNDLED_SOUL=ON`, the latest built soul `.so` to `~/.local/lib` diff --git a/arken/CMakeLists.txt b/ark/CMakeLists.txt index 9219879..35e47a9 100644 --- a/arken/CMakeLists.txt +++ b/ark/CMakeLists.txt @@ -1,31 +1,34 @@ cmake_minimum_required(VERSION 3.10) project ( - arken + ark VERSION 0.1 LANGUAGES C) set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_BUILD_TYPE Debug) -set(WLROOTS_VERSION "0.18") -set(WLROOTS_URL "https://gitlab.freedesktop.org/wlroots/wlroots/-/archive/${WLROOTS_VERSION}/wlroots-${WLROOTS_VERSION}.tar.gz") -set(WLROOTS_TARBALL "${CMAKE_BINARY_DIR}/wlroots-${WLROOTS_VERSION}.tar.gz") -set(WLROOTS_SOURCE_DIR "${CMAKE_BINARY_DIR}/wlroots-src") -set(WLROOTS_BUILD_DIR "${CMAKE_BINARY_DIR}/wlroots") -set(WLROOTS_LIB_STATIC "${WLROOTS_BUILD_DIR}/libwlroots-${WLROOTS_VERSION}.a") -set(WLROOTS_LIB_LINK "${WLROOTS_BUILD_DIR}/libwlroots.a") - -add_custom_command( - OUTPUT "${WLROOTS_LIB_LINK}" - COMMAND sh -c "if [ ! -d \"$1\" ]; then mkdir -p \"$1\" && curl -L \"$2\" | tar xzf - --strip-components=1 -C \"$1\"; fi" sh "${WLROOTS_SOURCE_DIR}" "${WLROOTS_URL}" - COMMAND "${CMAKE_COMMAND}" -E make_directory "${WLROOTS_BUILD_DIR}" - COMMAND meson setup --reconfigure -Ddefault_library=static "${WLROOTS_BUILD_DIR}" "${WLROOTS_SOURCE_DIR}" - COMMAND meson compile -C "${WLROOTS_BUILD_DIR}" - COMMAND "${CMAKE_COMMAND}" -E create_symlink "${WLROOTS_LIB_STATIC}" "${WLROOTS_LIB_LINK}" - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" - COMMENT "Building wlroots via Meson (static)" - VERBATIM -) +if(NOT TARGET wlroots_build) + set(WLROOTS_VERSION "0.18") + set(WLROOTS_URL "https://gitlab.freedesktop.org/wlroots/wlroots/-/archive/${WLROOTS_VERSION}/wlroots-${WLROOTS_VERSION}.tar.gz") + set(WLROOTS_SOURCE_DIR "${CMAKE_BINARY_DIR}/wlroots-src") + set(WLROOTS_BUILD_DIR "${CMAKE_BINARY_DIR}/wlroots") + set(WLROOTS_LIB_STATIC "${WLROOTS_BUILD_DIR}/libwlroots-${WLROOTS_VERSION}.a") + set(WLROOTS_LIB_LINK "${WLROOTS_BUILD_DIR}/libwlroots.a") + + add_custom_command( + OUTPUT "${WLROOTS_LIB_LINK}" + COMMAND sh -c "if [ ! -d \"$1\" ]; then mkdir -p \"$1\" && curl -L \"$2\" | tar xzf - --strip-components=1 -C \"$1\"; fi" sh "${WLROOTS_SOURCE_DIR}" "${WLROOTS_URL}" + COMMAND "${CMAKE_COMMAND}" -E make_directory "${WLROOTS_BUILD_DIR}" + COMMAND meson setup --reconfigure -Ddefault_library=static "${WLROOTS_BUILD_DIR}" "${WLROOTS_SOURCE_DIR}" + COMMAND meson compile -C "${WLROOTS_BUILD_DIR}" + COMMAND "${CMAKE_COMMAND}" -E create_symlink "${WLROOTS_LIB_STATIC}" "${WLROOTS_LIB_LINK}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + COMMENT "Building wlroots via Meson (static)" + VERBATIM + ) + + add_custom_target(wlroots_build ALL DEPENDS "${WLROOTS_LIB_LINK}") +endif() include_directories(include/ /usr/include/pixman-1 ${CMAKE_CURRENT_BINARY_DIR}/ @@ -77,9 +80,6 @@ file (GLOB_RECURSE SOURCES src/*.c) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -add_executable (arken ${SOURCES} ${WLROOTS_LIB_LINK} - xdg-shell-protocol.c) - find_package(PkgConfig REQUIRED) pkg_check_modules(WLREQ REQUIRED IMPORTED_TARGET @@ -98,7 +98,10 @@ pkg_check_modules(WLREQ REQUIRED IMPORTED_TARGET glesv2 ) -target_link_libraries(arken PRIVATE PkgConfig::WLREQ dl pthread ${WLROOTS_LIB_LINK}) +add_executable (ark ${SOURCES} ${WLROOTS_LIB_LINK} + xdg-shell-protocol.c) + +target_link_libraries(ark PRIVATE PkgConfig::WLREQ dl pthread ${WLROOTS_LIB_LINK}) pkg_check_modules(WLOPT IMPORTED_TARGET cairo @@ -123,9 +126,9 @@ pkg_check_modules(WLOPT IMPORTED_TARGET ) if(WLOPT_FOUND) - target_link_libraries(arken PRIVATE PkgConfig::WLOPT) + target_link_libraries(ark PRIVATE PkgConfig::WLOPT) endif() -target_link_directories(arken PUBLIC +target_link_directories(ark PUBLIC "${WLROOTS_BUILD_DIR}") -target_link_options(arken PRIVATE -rdynamic) +target_link_options(ark PRIVATE -rdynamic) diff --git a/ark/README.md b/ark/README.md new file mode 100644 index 0000000..d773e0d --- /dev/null +++ b/ark/README.md @@ -0,0 +1,51 @@ +Ark (Runtime) +============= + +Ark is a long-running Wayland compositor runtime with a hot-reloadable soul +interface. + +Responsibilities +---------------- + +- Owns the Wayland display lifecycle and wlroots setup. +- Loads a soul shared object (`.so`) at runtime and routes input/surface events to it. +- Supports hot-reloading the soul without restarting the compositor. + +Soul interface +-------------- + +The runtime defines a C ABI that souls must implement (load/start/teardown, +event handlers, and optional state marshal/unmarshal for hot reload). The ABI is +defined in: + +- `ark/include/soul.h` + +Souls should include: + +- `ark/include/soul_interface.h` + +Key files +--------- + +- `ark/src/wl.c`: compositor setup + event loop + soul callbacks. +- `ark/src/soul.c`: dynamic loading, lifecycle, and hot-reload logic. +- `ark/include/soul.h`: C ABI the soul must implement. + +Building +-------- + +Ark is built via the top-level CMake project: + +```sh +cmake -S .. -B ../build +cmake --build ../build --target ark +``` + +Running +------- + +Use the top-level `run` target (builds the bundled soul and launches Ark): + +```sh +cmake --build ../build --target run +``` diff --git a/ark/include/soul.h b/ark/include/soul.h new file mode 100644 index 0000000..fa3415b --- /dev/null +++ b/ark/include/soul.h @@ -0,0 +1,111 @@ +#ifndef _SOUL_H_ +#define _SOUL_H_ + +#include <dlfcn.h> +#include <linux/limits.h> +#include <pthread.h> +#include <stdint.h> +#include <wlr/types/wlr_input_device.h> +#include <wlr/types/wlr_keyboard.h> +#include <wlr/types/wlr_pointer.h> + +#include "soul_types.h" +#include "soul_exports.h" + +#define MAX_QUEUED_ACTIONS 8 + +typedef void *dlhandle_t; + +/* Opaque state for a soul. Not to be touched by the harness (not that it + * really can be.) */ + +struct SOUL; +/* This structure represents an action requested by the soul for the harness. + */ +typedef struct { + int (*action)(struct SOUL *requester, void *arg); + void (*arg_dtor)(void *arg); + union { + void *ptr_arg; + int int_arg; + char *str_arg; + }; +} requested_action_t; + +/* + * Structure for the soul. + */ +typedef struct SOUL { + /* The argc this soul is loaded with. Typically the argc from main(). */ + int argc; + + /* The argv this soul is loaded with. Typically the argv from main(). */ + char **argv; + + /* Filename the soul is loaded from. */ + char filename[PATH_MAX]; + + /* Opaque state of this soul. The state is usually some kind of pointer to + * the soul state, but all the harness knows is the opaque state is a + * pointer-sized piece of data. + * + * This opaque state is used in a linear pattern where the handlers take the + * opaque state, maybe operate on it, and return a new opaque state, which is + * then passed to the next handler, etc. It is on the soul to properly + * manager the memory for this state and to destroy it upon teardown. + * + * It's guaranteed that this state is used linearly, meaning the harness gives + * up all ownership to it once passed into a handler. */ + opqst_t state; + + /* This soul's lock. This avoids potential issues with multiple threads + * trying to change the opaque state at once which can lead to undesireable + * outcomes. */ + pthread_mutex_t lock; + + /** Set to not-zero if this soul is initialized, otherwise set to zero. */ + int initialized; + + /* The handle to the shared library. */ + dlhandle_t library_handle; + + /* Pointer to the soul name. This is in the shared library and a + * null-terminated string. If the library does not have a soul name, this + * will be NULL. */ + const char *soul_name; + + /* Soul function table populated by the runtime loader. */ +#define SOUL_FN_PTR(ret, name, args) ret (*name) args; + ARKSOUL_EXPORTS(SOUL_FN_PTR) +#undef SOUL_FN_PTR + + /* List of requested actions by the soul. Right now there is a maximum of 8 + * allowed at one time. That should be plenty. The actions should be flushed + * after each call to a handler anyway. */ + size_t n_requested_actions; + requested_action_t requested_actions[MAX_QUEUED_ACTIONS]; +} soul_t; + +/* Reloads the soul. This tears down the existing soul, marshals the state + * for it and reloads it. + * + * This function will call dlclose on the soul's library handle. + */ +int soul_hot_reload(int argc, char **argv, const char *filepath, soul_t *soul); + +/* + * Like hot-reload, but uses the same parameters the soul was originally + * loaded with. + */ +int soul_hot_reload_same_state(soul_t *soul); + +/* Starts a soul in a cold state. Called after load_soul_from_file. */ +void soul_cold_start(soul_t *soul); + +/* Reads a soul from a filename. */ +int load_soul_from_file(int argc, char **argv, const char *filename, + soul_t *soul); + +void soul_run_requested_actions(soul_t *soul); + +#endif /* _SOUL_H_ */ diff --git a/arken/include/plugin_exports.h b/ark/include/soul_exports.h index 4518d92..8e22b15 100644 --- a/arken/include/plugin_exports.h +++ b/ark/include/soul_exports.h @@ -1,42 +1,42 @@ #pragma once /* - * Single source of truth for the plugin ABI. + * Single source of truth for the soul ABI. * * Consumers must define an X-macro like: * #define X(ret, name, args) ... * and then invoke: - * MONTIS_PLUGIN_EXPORTS(X) + * ARKSOUL_EXPORTS(X) * * Note: this file intentionally does not include headers. Include whatever you - * need (e.g. <stdint.h>, plugin_types.h, wlroots headers) before expanding. + * need (e.g. <stdint.h>, soul_types.h, wlroots headers) before expanding. */ -#define MONTIS_PLUGIN_EXPORTS(X) \ +#define ARKSOUL_EXPORTS(X) \ /* \ - * `plugin_metaload` \ + * `arksoul_export_metaload` \ * \ - * Called at most once per process *per `plugin_name`*. This is the place \ + * Called at most once per process *per `soul_name`*. This is the place \ * for truly global initialization that should survive hot reloads (e.g. \ * one-time language runtime init, registering global hooks, etc.). \ * \ * Notes: \ * - May be a no-op. \ - * - Must be safe to call before any other plugin entrypoint. \ + * - Must be safe to call before any other soul entrypoint. \ */ \ - X(void, plugin_metaload, (int argc, char **argv)) \ + X(void, arksoul_export_metaload, (int argc, char **argv)) \ /* \ - * `plugin_load` \ + * `arksoul_export_load` \ * \ * Called every time the shared object is loaded (cold start and each hot \ * reload). Use this for per-load initialization that must be re-done after \ * `dlopen`. \ */ \ - X(void, plugin_load, (int argc, char **argv)) \ + X(void, arksoul_export_load, (int argc, char **argv)) \ /* \ - * `plugin_hot_start` \ + * `arksoul_export_rebirth` \ * \ - * Called after a hot reload with the previous plugin's marshalled state. \ + * Called after a hot reload with the previous soul's preserved state. \ * Must return the new live opaque state (`opqst_t`) to be used for future \ * handler calls. \ * \ @@ -45,56 +45,56 @@ * - `self` is an opaque pointer owned by the runtime; treat it as \ * read-only. \ */ \ - X(opqst_t, plugin_hot_start, \ + X(opqst_t, arksoul_export_rebirth, \ (void *self, uint8_t *marshalled_state, uint32_t n)) \ /* \ - * `plugin_cold_start` \ + * `arksoul_export_ensoul` \ * \ * Called on first boot when no previous state exists. Must construct and \ * return an initial opaque state. \ */ \ - X(opqst_t, plugin_cold_start, (void *self)) \ + X(opqst_t, arksoul_export_ensoul, (void *self)) \ /* \ - * `plugin_marshal_state` \ + * `arksoul_export_preserve` \ * \ - * Called before unloading the current plugin during hot reload. Must \ + * Called before unloading the current soul during hot reload. Must \ * serialize the provided opaque state into a newly allocated byte buffer. \ * \ * Ownership: \ * - Return a heap-allocated buffer (e.g. `malloc`). \ * - The runtime takes ownership and will `free()` it after \ - * `plugin_hot_start`. \ + * `arksoul_export_rebirth`. \ */ \ - X(uint8_t *, plugin_marshal_state, (opqst_t st, uint32_t *szout)) \ + X(uint8_t *, arksoul_export_preserve, (opqst_t st, uint32_t *szout)) \ /* \ - * `plugin_teardown` \ + * `arksoul_export_release` \ * \ * Called immediately before the shared object is unloaded. Use this to \ * release resources owned by the opaque state (and any per-load resources \ - * created in `plugin_load`). \ + * created in `arksoul_export_load`). \ */ \ - X(void, plugin_teardown, (opqst_t st)) \ + X(void, arksoul_export_release, (opqst_t st)) \ /* \ - * `plugin_handle_keybinding` \ + * `arksoul_export_handle_keybinding` \ * \ * Called for keyboard events. Returns the updated opaque state. Set \ * `*out_handled` to non-zero if the event is consumed. \ */ \ - X(opqst_t, plugin_handle_keybinding, \ + X(opqst_t, arksoul_export_handle_keybinding, \ (struct wlr_keyboard * keyboard, struct wlr_keyboard_key_event * event, \ uint32_t modifiers, uint32_t keysym, uint32_t codepoint, \ int *out_handled, opqst_t state)) \ /* \ - * `plugin_handle_button` \ + * `arksoul_export_handle_button` \ * \ * Called for pointer button events (mouse/trackpad clicks). Returns the \ * updated opaque state. \ */ \ - X(opqst_t, plugin_handle_button, \ + X(opqst_t, arksoul_export_handle_button, \ (struct wlr_pointer_button_event * event, uint32_t modifiers, \ opqst_t state)) \ /* \ - * `plugin_handle_motion` \ + * `arksoul_export_handle_motion` \ * \ * Called for pointer motion. Returns the updated opaque state. \ * \ @@ -103,15 +103,15 @@ * (type depends on `is_absolute`). \ * - `lx`/`ly` are layout coordinates in compositor space. \ */ \ - X(opqst_t, plugin_handle_motion, \ + X(opqst_t, arksoul_export_handle_motion, \ (void *event, uint32_t modifiers, uint32_t is_absolute, double lx, \ double ly, opqst_t state)) \ /* \ - * `plugin_handle_surface` \ + * `arksoul_export_handle_surface` \ * \ * Called when a surface is mapped/unmapped/destroyed. `surface` is an \ - * opaque pointer to the runtime surface representation. Returns the updated \ - * opaque state. \ + * opaque pointer to the runtime surface representation. Returns the updated \ + * opaque state. \ */ \ - X(opqst_t, plugin_handle_surface, \ + X(opqst_t, arksoul_export_handle_surface, \ (void *surface, surface_event_t event, opqst_t state)) diff --git a/ark/include/soul_interface.h b/ark/include/soul_interface.h new file mode 100644 index 0000000..6e45573 --- /dev/null +++ b/ark/include/soul_interface.h @@ -0,0 +1,23 @@ +#ifndef _SOUL_INTF +#define _SOUL_INTF + +#include <stdint.h> + +#include "soul_types.h" +#include "soul_exports.h" + +#include <wlr/types/wlr_input_device.h> +#include <wlr/types/wlr_keyboard.h> +#include <wlr/types/wlr_pointer.h> + +/* + * Soul ABI: souls must export these symbols. + * + * This header is intended to be included by soul implementations. + */ + +#define DECLARE_SOUL_EXPORT(ret, name, args) ret name args; +ARKSOUL_EXPORTS(DECLARE_SOUL_EXPORT) +#undef DECLARE_SOUL_EXPORT + +#endif /* _SOUL_INTF */ diff --git a/arken/include/plugin_types.h b/ark/include/soul_types.h index df1eab5..df1eab5 100644 --- a/arken/include/plugin_types.h +++ b/ark/include/soul_types.h diff --git a/arken/include/wl.h b/ark/include/wl.h index f10ee7d..e5cf4f3 100644 --- a/arken/include/wl.h +++ b/ark/include/wl.h @@ -26,7 +26,7 @@ #include <wlr/util/log.h> #include <xkbcommon/xkbcommon.h> -#include <plugin.h> +#include <soul.h> /* For brevity's sake, struct members are annotated where they are used. */ enum montis_cursor_mode { |