├── .envrc ├── .github ├── README.md └── workflows │ └── deploy.yml ├── .gitignore ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── build.rs ├── docs ├── .vitepress │ ├── config.mts │ └── theme │ │ ├── index.ts │ │ └── tabs.css ├── assets │ └── software-buttons-visualized.svg ├── configuration │ ├── animations.md │ ├── cursor.md │ ├── decorations.md │ ├── general.md │ ├── input.md │ ├── introduction.md │ ├── keybindings.md │ ├── layer-rules.md │ ├── mousebindings.md │ ├── outputs.md │ └── window-rules.md ├── getting-started │ ├── example-nix-setup.md │ ├── guided-tour.md │ ├── important-software.md │ ├── installing.md │ └── introduction.md ├── index.md ├── package-lock.json ├── package.json ├── public │ └── assets │ │ ├── default-output-arrangement.svg │ │ ├── elastic.png │ │ ├── master-slave-stacks.png │ │ ├── mwfact.svg │ │ ├── preview.png │ │ ├── proportion-changes.svg │ │ └── xwayland.png └── usage │ ├── ipc.md │ ├── layouts.md │ ├── nix.md │ ├── portals.md │ ├── workspaces.md │ └── xwayland.md ├── fht-compositor-config ├── Cargo.toml └── src │ └── lib.rs ├── flake.lock ├── flake.nix ├── res ├── compositor.toml ├── cursor.rgba ├── fht-compositor-portals.conf ├── fht-compositor-uwsm.desktop ├── fht-compositor.desktop ├── fht-compositor.portal └── preview.png ├── rust-toolchain.toml ├── rustfmt.toml └── src ├── backend ├── mod.rs ├── udev.rs └── winit.rs ├── cli.rs ├── config ├── mod.rs └── ui.rs ├── cursor.rs ├── egui.rs ├── focus_target.rs ├── frame_clock.rs ├── handlers ├── alpha_modifiers.rs ├── buffer.rs ├── compositor.rs ├── content_type.rs ├── cursor_shape.rs ├── data_control.rs ├── data_device.rs ├── dmabuf.rs ├── dnd.rs ├── drm_lease.rs ├── drm_syncobj.rs ├── foreign_toplevel_list.rs ├── fractional_scale.rs ├── idle_inhibit.rs ├── input_method.rs ├── keyboard_shortcuts_inhibit.rs ├── layer_shell.rs ├── mod.rs ├── output.rs ├── output_management.rs ├── pointer_constraints.rs ├── pointer_gestures.rs ├── presentation.rs ├── primary_selection.rs ├── relative_pointer.rs ├── screencopy.rs ├── seat.rs ├── security_context.rs ├── selection.rs ├── session_lock.rs ├── shm.rs ├── single_pixel_buffer.rs ├── viewporter.rs ├── virtual_keyboard.rs ├── xdg_activation.rs ├── xdg_decoration.rs ├── xdg_dialog.rs ├── xdg_foreign.rs └── xdg_shell.rs ├── input ├── actions.rs ├── mod.rs ├── resize_tile_grab.rs └── swap_tile_grab.rs ├── layer.rs ├── main.rs ├── output.rs ├── portals ├── mod.rs ├── screencast.rs └── shared.rs ├── profiling.rs ├── protocols ├── mod.rs ├── output_management.rs └── screencopy.rs ├── renderer ├── blur │ ├── element.rs │ ├── mod.rs │ └── shader.rs ├── data.rs ├── extra_damage.rs ├── mod.rs ├── pixel_shader_element.rs ├── render_elements.rs ├── rounded_element │ └── shader_.frag ├── rounded_window.rs ├── shaders │ ├── blur-down.frag │ ├── blur-finish.frag │ ├── blur-up.frag │ ├── border.frag │ ├── box-shadow.frag │ ├── mod.rs │ ├── resizing-texture.frag │ ├── rounded-window.frag │ └── texture.vert ├── texture_element.rs └── texture_shader_element.rs ├── space ├── closing_tile.rs ├── decorations.rs ├── mod.rs ├── monitor.rs ├── tile.rs └── workspace.rs ├── state.rs ├── utils ├── mod.rs └── pipewire.rs └── window.rs /.envrc: -------------------------------------------------------------------------------- 1 | strict_env 2 | use flake . 3 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 |
A dynamic tiling Wayland compositor.
3 | 8 | 9 |  10 | 11 | 12 | ## About 13 | 14 | `fht-compositor` is a dynamic tiling Wayland compositor that implements a window management model 15 | inspired by X11 window managers such as [dwm](https://dwm.suckless.org) and [xmonad](https://xmonad.org) 16 | 17 | 18 | Each output gets assigned 9 independent workspaces, each one holding windows that get automatically 19 | arranged on the screen space using layouts, minimizing lost screen real estate, and providing a 20 | keyboard-focused workflow 21 | 22 | 23 | In addition, the compositor also provides some nice-to-have features that elevate the experience 24 | from a visual and practical standpoint, see features for more information. 25 | 26 | ## Video demo 27 | 28 | https://github.com/user-attachments/assets/4ea9b294-85a8-49ab-9f42-2f76111f063b 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy documentation 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths: 7 | - docs/** 8 | # Also allows me to rebuild manually from the actionss tab 9 | workflow_dispatch: 10 | 11 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 12 | permissions: 13 | contents: read 14 | pages: write 15 | id-token: write 16 | 17 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 18 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 19 | concurrency: 20 | group: pages 21 | cancel-in-progress: false 22 | 23 | jobs: 24 | # Build job 25 | build: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v4 30 | with: 31 | fetch-depth: 0 # Not needed if lastUpdated is not enabled 32 | # - uses: pnpm/action-setup@v3 # Uncomment this block if you're using pnpm 33 | # with: 34 | # version: 9 # Not needed if you've set "packageManager" in package.json 35 | # - uses: oven-sh/setup-bun@v1 # Uncomment this if you're using Bun 36 | - name: Setup Node 37 | uses: actions/setup-node@v4 38 | with: 39 | node-version: 20 40 | cache: npm # or pnpm / yarn 41 | cache-dependency-path: docs/package-lock.json 42 | - name: Setup Pages 43 | uses: actions/configure-pages@v4 44 | - name: Install dependencies 45 | run: cd docs && npm ci # or pnpm install / yarn install / bun install 46 | - name: Build with VitePress 47 | run: cd docs && npm run docs:build # or pnpm docs:build / yarn docs:build / bun run docs:build 48 | - name: Upload artifact 49 | uses: actions/upload-pages-artifact@v3 50 | with: 51 | path: docs/.vitepress/dist 52 | 53 | # Deployment job 54 | deploy: 55 | environment: 56 | name: github-pages 57 | url: ${{ steps.deployment.outputs.page_url }} 58 | needs: build 59 | runs-on: ubuntu-latest 60 | name: Deploy 61 | steps: 62 | - name: Deploy to GitHub Pages 63 | id: deployment 64 | uses: actions/deploy-pages@v4 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | # Useless log files in the repo 3 | std* 4 | # when building with nix 5 | /result 6 | # direnv cache 7 | /.direnv 8 | 9 | # Documentation/wiki, generated with vitepress 10 | # cache and dist are used when building/previewing the site 11 | docs/node_modules 12 | docs/.vitepress/cache 13 | docs/.vitepress/dist 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution guide 2 | 3 | Some insight and guidelines for contribution to the compositor. 4 | 5 | - Formatting is done using `cargo +nightly fmt` 6 | - Current MSRV is `nightly`, due to [this](https://github.com/rust-lang/rust/issues/95439) 7 | - Keep your git commit titles short, expand in their descriptions (your editor should have settings for this) 8 | 9 | ## Logging 10 | 11 | There exist four kind of log levels: 12 | - `info!`: For information message, if some *important enough* action succeeded 13 | - `warn!`: For error/unexpected behaviour, but ***not** important enough* to alter compositor activity 14 | - `error!`: For error/unexpected behaviour, that is *important enough* to alter compositor activity 15 | - `debug!`: For keeping track of events and actions that matter for developers, not end users 16 | 17 | Additional directives are 18 | - Avoid punctuation when logging messages 19 | - use tracing's `?value` to specify arguments, unless it hurts user readability, for example `warn!(?err, "msg")` 20 | 21 | ## Code organization 22 | 23 | - `backend::*`: Backend-only interaction 24 | - `config::*`: Config types 25 | - `handlers::*`: Custom `*Handler` trait types or `delegate_*` macros, required by smithay. 26 | - `portals::*`: [XDG desktop portals](https://flatpak.github.io/xdg-desktop-portal/) 27 | - `renderer::*`: Rendering and custom render elements 28 | - `shell::*`: Modules related to the desktop shell with `xdg-shell`, `wlr-layer-shell`, workspaces, etc. 29 | - `utils::*`: General enough utilities (optimally I'd get rid of this) 30 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # {{{ Workspace 2 | 3 | [workspace] 4 | members = ["fht-compositor-config"] 5 | resolver = "2" 6 | 7 | [workspace.package] 8 | version = "25.3.1" 9 | description = "A dynamic tiling Wayland compositor" 10 | authors = ["Nadjib Ferhat