{"id":18868011,"url":"https://github.com/marcusgrass/pgwm","last_synced_at":"2025-05-07T17:45:06.626Z","repository":{"id":38616603,"uuid":"479151447","full_name":"MarcusGrass/pgwm","owner":"MarcusGrass","description":"A minimal tiling x11 window manager","archived":false,"fork":false,"pushed_at":"2025-03-21T19:32:39.000Z","size":3884,"stargazers_count":69,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-31T12:22:54.160Z","etag":null,"topics":["rust","x11-wm"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MarcusGrass.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-07T21:18:27.000Z","updated_at":"2025-03-21T19:32:42.000Z","dependencies_parsed_at":"2024-05-05T11:31:36.544Z","dependency_job_id":"bed38b96-095d-4178-bb9d-b8074db3923f","html_url":"https://github.com/MarcusGrass/pgwm","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarcusGrass%2Fpgwm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarcusGrass%2Fpgwm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarcusGrass%2Fpgwm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarcusGrass%2Fpgwm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MarcusGrass","download_url":"https://codeload.github.com/MarcusGrass/pgwm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252928942,"owners_count":21826776,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rust","x11-wm"],"created_at":"2024-11-08T05:12:28.154Z","updated_at":"2025-05-07T17:45:06.606Z","avatar_url":"https://github.com/MarcusGrass.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PGWM, a DWM-inspired tiling window manager written in pure Rust\n[![Latest workflow](https://github.com/MarcusGrass/pgwm/workflows/CI/badge.svg)](https://github.com/MarcusGrass/pgwm/actions)\n\nThe WM is to my understanding compliant with the [wm-spec](https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html).\nThe specification is fairly difficult to understand (for me) and for a tiling window manager some sometimes liberal\ninterpretations has to be made. If something seems implemented wrongly, and it isn't covered by\nan explanation in [EWMH.md](docs/EWMH.md), please create an issue if you have the time.\nBig shout out to [x11rb](https://github.com/psychon/x11rb) which has great safe x11 bindings!\n\nEven Jetbrains IDE's work without freaking out assuming `setwmname LG3D` is in your `~/.xinitrc`.\n\n\n# Why\nI love to build my old tools, so after a few years of running up against bugs that bothered my workflow \nand features that I wanted but were missing in other tiling WMs\nI decided to build a WM that does exactly what I want it to do. I considered hacking dwm, but I'm not that hot with \n`C` and decided against it, opting to write it in Rust instead. \n\n# Primary goals\nA WM that is fast, has low resource-usage, is feature complete according to my needs,\ndoesn't contain nasty bugs or QoL-detriments, and is ewmh-compliant.\n\n# Implemented features\n- Crashes on errors (yes this is a feature)\n- It can tile windows in a left-leader or center-leader pattern\n- It can display windows tabbed with the window title on top\n- Windows are configured into workspaces\n- Workspaces can be moved between monitors\n- Workspace-layouts can be cycled (left-leader -\u003e center-leader -\u003e tabbed)\n- Windows within workspaces can have their order rearranged\n- Windows can be moved between workspaces\n- When a window is moved from a workspace it ends up at the first tab-order\n- Windows can be manually floated\n- Floating windows can be dragged\n- Windows can be manually un-floated\n- It hosts a bar at the top of each monitor\n- Sections of the bar can have their on-click behaviour customized\n- The bar can be hidden\n- The displays workspace information, window title name, status-checks, and shortcuts\n- Windows can be resized\n- Visible cursor without window supplying it\n- Most of the window-manipulation that the WM does can be configured\n- Keys (or clickable sections of the bar) can be configured to run arbitrary processes (some custom bash for example)\n- Windows can be mapped to workspaces by their `WM_CLASS` property\n\n# Comparison to other WMs\nI'm only comparing other WMs which I have used extensively hopefully I can extend this to include more than 2 other WMs.\n\n## DWM\nThe closest WM in terms of feature-parity would be DWM, although this WM tries to do a bit more by default than DWM does.\nA major difference between this WM and DWM is that instead of using tags with\ndifferent tags per monitor this WM operates closer to DWM's [single tagset patch](https://dwm.suckless.org/patches/single_tagset/).\n\n## Xmonad\nThe beauty of xmonad and using haskel for a configurable WM is that through a functional language Xmonad provides\nan absurd level of customizability, this lends itself well to contributors creating additions through xmonad-contrib.\nThis WM does not aim to match that level of customizability but instead tries to be minimal and reasonably configurable,\nwhile also being distributable and configurable through a binary rather than compiled-configuration. Something like [penrose](https://github.com/sminez/penrose) \nis likely what you're looking for if you want something more Xmonad-like.\n\n# Usage\nSome getting-started information is described [here](docs/USAGE.md).\n\n# Future plans\nAs far as features go the plan is not to add complicated features, but simple flexible things. The WM is now \naccording to my needs feature complete. However, I most likely don't know what I'm missing, if there's a feature \nthat you'd like to see I'd love to hear about it and will consider adding it, but I am fairly conservative when it \ncomes to adding features that I wouldn't use, the best place for those would be a fork.\nWhen it comes to ergonomics and documentation I'm very open to add things. One big thing is the configuration,\nit's a simplest possible mapping, almost 1 to 1 to internal datastructures which makes it cumbersome.\nInstead of configuring a status check in one place, and then a mouse-mapping on click for it in another \nsomething more reasonable might be to configure a status check and in the same place some on-click action, things like that.\nI've been hesitant about working too much on configuration ergonomics since I don't know if there is any demand for that, \nif there is, please let me know by creating an issue.\n\n# How it looks\n### Default config, tabbed on the left, left-leader-layout on the right.\n![multi-monitor-tiled](demo1.png)\n### Default config, left-leader-layout on the left, a floating window on the right, above the left-leader-layout\n![multi-monitor-tabbed-float](demo2.png)\n### Default config, single monitor center-leader\n![multi-monitor-tabbed-float](demo3.png)\n\n# How to build\nTo build locally, platform build essentials is required\nsee the [min building dockerfile](.docker/minimal-build.dockerfile).  \nTo run the same test as the ci locally, libssl and perl is also required, \n[see the ci dockerfile](.docker/full-checks.dockerfile).\n\nThe project is tested on x86_64-unknown-linux-gnu but \"should\" run on more *nix systems. \n\n## Install a Rust toolchain\nhttps://www.rust-lang.org/tools/install\n\n## Clone this repo\ngit clone https://github.com/MarcusGrass/pgwm.git\n\n## Build the project\nAs of 0.3.0 the WM runs in pure Rust with no libc dependencies. In effect this means that the binary will always be \nstatically linked. It also sadly means that some use of unsafety is needed.\nMostly this comes from direct syscalls, which will always be unsafe, as well as the WM entrypoint since we don't include start files.\n\nAnother side effect of this is that a target needs to be specified for build-scripts in dependencies to run correctly \nsince the binary will be statically linked anyway it just defaults to --target x86_64-unknown-linux-gnu in [the build script](build_wm.sh).\n\n`lld` is required, if you don't want to change [the small build script](build_wm.sh) and remove it as the default linker there.\n\nThe project builds default with xinerama support, and a status-bar. To compile without either,\ndisable default features.\nTo build with max optimizations use --profile=lto.\nIn [config.toml](.cargo/config.toml) --release is set to compile with debug assertions, usually when I'm developing \nthe WM I run it like that to ensure that there are no overflows/underflows, x11 uses i16s, u16s, i32s, and u32s fairly interchangeably \nwhich poses a conversion risk. Removing that option will yield a negligible performance increase if compiling --release.    \nIn benchmarking, heavier calculations see a speedup of around 15-45% on lto compared to release on my machine, \nthat being said we're talking about 190 to 150 nanoseconds for calculating tiling positions, there aren't many heavy calculations\nbeing performed, most latency is from x11 redrawing windows.  \nThe project can also be compiled with debug output, the binary will then output various debug info to stderr.\n\n### Using make\nThere's a [configure script](configure) for convenience, although it's basically just\na silly posix-shell script that generates a Makefile.\n\nIf no binary directory is supplied, the script will try to install to `$HOME/.local/bin`, \nif the environment variable `$HOME` is not set and no binary directory is supplied the script will fail.  \nif your path variable doesn't include that directory you can export that for example in your `~/.bashrc` \nwith: `export PATH=$HOME/.local/bin:$PATH`, if you want the wm to be launchable by just `pgwm`.  \n\n  \nBuild default:  \n```shell\n./configure\nmake\nmake install\n# Cleans up build directory\nmake clean\n```\nUse `./configure --help` to see options, by default uninstall does not remove the configuration file, the full lifecycle from nothing\nto a clean uninstall would be\n```shell\n./configure\nmake\nmake install\nmake clean\n# Uninstall and remove config\nmake uninstall CLEAN_CONFIG=1\n```\n\n### Manual build\nHow to build as a regular Rust project.\n\n#### With default features\n`./build_wm.sh -r`\nor\n`./build_wm.sh --profile=lto`\n\n#### With no default features\n`./build_wm.sh --release --no-default-features`\nor\n`./build_wm.sh --profile=lto --no-default-features`\n\n#### Example of some additional features\n`./build_wm.sh --release --no-default-features --features xinerama,status-bar`  \nor  \n`./build_wm.sh --profile=lto --no-default-features --features xinerama,status-bar`\n\n### Edit .xinitrc or other file specifying WM entrypoint\nIf built with `./build_wm.sh` The binary ends up in target/x86_64-unknown-linux-gnu/release/pgwm or target/x86_64-unknown-linux-gnu/lto/pgwm\nReplace the (probably) last line of .xinitrc with\n`exec $BINARY_LOCATION` $BINARY_LOCATION being the path to the pgwm binary.     \n\n# Changing configuration\nConfiguration resides in [pgwm_core/src/config/mod.rs](pgwm-core/src/config/mod.rs) and consists of rust code.\nThe configuration is mostly constants with some functions, some constants are limits, such as `WS_WINDOW_LIMIT`,\nthe reason for it existing is that a lot of heapless datastructures are used.\nIf you were to set the `WS_WINDOW_LIMIT` to 2, and try to spawn 3 windows on a workspace, the application would crash.\nA rule of thumb for the error-handling is that all errors which are unexpected immediately causes a crash, and every crash\nsignifies a misconfiguration or programming error. The reason for keeping it this way is so that bugs doesn't go by silently.\nIf something causes a crash I want to fix the issue rather than have the application limp along. \nIf you decide to try this WM out and find a bug, please report it as an issue in this repo or make a PR if you have the time.  \n\nNote: A crash here is a rust `panic`, the WM should never segfault, regardless of misconfiguration. If it does please \nfile an issue.\n\n# Easy mistakes to make\nThere are a few easy mistakes to make that will make the WM run strangely. \n- The configured fonts do not exist on the machine. The default configuration of this WM is one that I use, and if you do not\nhave the same fonts as I do the results will be weird. Update the default configuration to use a font that exists on the machine.\n`fc-list` will find available fonts.\n- Misconfiguration causing startup issues, if the issues start after increasing something, more fonts, more keybinds etc.\nThen most likely a hardcoded limit has been reached, either create an Issue to increase the limit, recompile it yourself with a higher limit, \nor make a PR with the limit increased. Limits are found [with the hardcoded configuration](pgwm-core/src/config/mod.rs).\n- Fewer defined workspaces than amount of monitors will result in unused monitors\n- If running some applications built on java frameworks, such as Jetbrains IDE's, \nputting the below lines in your `~/.xinitrc` may be required for them to work properly.\n```Bash\nexport _JAVA_AWT_WM_NONREPARENTING=1\nexport AWT_TOOLKIT=MToolkit\nwmname compiz # or wmname LG3D\n```\n\n# Resources\nThe WM, according to `smem` on glibc, has a USS/PSS/RSS of around 2M when built for musl with the lto profile and no known leaks,\na memory leak would likely result in a crash rather than a slow increase over time since most dynamic\ndata structures are on the stack.  \nCPU-wise it has a fairly low usage, with idle usage that depends completely on whether you use the status bar, what update frequency you're\nrunning it on, and which checks you're using. Running the full checks on a 1 second interval as I am doing currently draws very little cpu.\n\nSome update-intensive operations will cause cpu-spikes, such as dragging a floating window. For each motion-event coming from x11\nthe WM reconfigures the window. The same thing will occur if resizing tiled windows, each resize will cause a reconfiguration\nof windows in that tile-set.\n\nSome programs like Jetbrains IDEs update the WM name on every keystroke, depending on\ntyping speed this may result in a lot of events and workspace bar redraws. However, that operation is so CPU-efficient that it isn't worth\nmaking an effort to reduce workspace bar redraws on name-changes by caching or otherwise.\n\nSome examples to get a feel for the resource usage (the WM runs single threaded):  \nAt idle with no status bar I get a 0% single-core CPU usage, with status bar it spikes about once a second to 0.6%.  \nAn extremely violent window drag results in an at most 10% single-core CPU usage.  \nFurious typing into a Jetbrains IDE gets at most 1.3% single-core CPU usage.\n\nAll this being said, it's measured for the running WM binary, all operations on the x11-server will cause some overhead there,\nthis WM binary could be perfectly efficient but slamming the x11 server with requests that it has problems processing.\nAlthough I have not noticed any such behaviour.\n\nNote: post migration, pre rip out libc, 931K binary size\n\n# Licensing\nThis project is licensed under [GPL v3](GPL-LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcusgrass%2Fpgwm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcusgrass%2Fpgwm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcusgrass%2Fpgwm/lists"}