{"id":17526529,"url":"https://github.com/frap129/layman","last_synced_at":"2025-07-15T21:31:47.271Z","repository":{"id":47845175,"uuid":"465137811","full_name":"frap129/layman","owner":"frap129","description":"a layout management framework for sway/i3","archived":false,"fork":false,"pushed_at":"2024-03-05T15:49:45.000Z","size":20057,"stargazers_count":33,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-14T11:41:10.332Z","etag":null,"topics":["i3wm","master-stack","sway","swaywm","window-manager"],"latest_commit_sha":null,"homepage":"","language":"Python","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/frap129.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2022-03-02T03:05:34.000Z","updated_at":"2024-10-01T06:28:44.000Z","dependencies_parsed_at":"2024-03-05T16:47:33.708Z","dependency_job_id":"15e045d1-91c8-4253-a817-21e36c65f290","html_url":"https://github.com/frap129/layman","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frap129%2Flayman","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frap129%2Flayman/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frap129%2Flayman/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frap129%2Flayman/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frap129","download_url":"https://codeload.github.com/frap129/layman/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226071006,"owners_count":17569103,"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":["i3wm","master-stack","sway","swaywm","window-manager"],"created_at":"2024-10-20T15:01:57.124Z","updated_at":"2024-11-23T17:17:34.030Z","avatar_url":"https://github.com/frap129.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# layman\n\nlayman is a daemon that handles layout management on a per-workspace basis. Each `WorkspaceLayoutManager` (WLM) is\nresponsible for managing all of the tiling windows on a given workspace. \n\nWLMs are intended to have a simpler set of events than those provided though i3ipc-python, since the scope is limited\nto a single workspace. See the User Created Layouts section for how to add a new layout.\n\n```\nUsage: layman.py [options]\n\nOptions:\n  -h, --help                   show this help message and exit\n  -c .config/layman/config.toml, --config=.config/layman/config.toml\n                               Path to user config file.\n```\n\n## Installation\n\nI intend to provide installation through PyPi using pip, however the original name of this project `swlm` was forbidden for\nbeing too similar to another package, swmm. After rebranding to `layman`, the name is still forbidden for an unkown reason.\nUntil this is resolved, please use the instructions below.\n\nFor Arch users, `layman-git` is available [on the AUR](https://aur.archlinux.org/packages/layman-git) courtesy of [matclab](https://github.com/matclab)\n\n## Installing from source\n```\ngit clone https://github.com/frap129/layman\npip install ~/path/to/layman\n```\nto package and install layman. If you do not want to have to reinstall after a change, add --editable to the pip command\n\n## Configuration\n\nlayman is configured using the config file at `$HOME/.config/layman/config.toml`. The `[layman]` table configures\noptions for layman, and defaults options for WLMs. Specific outputs and workspaces can be configured using\n`[output.VALUE]` or `[workspace.VALUE]` header, where `VALUE` is the name of the output or the workspace number.\nAny options configured will override the values set in the `[layman]` table for that output or workspace. For an example\nconfiguration, see the `config.toml` file in the root of this repo.\n\nNote, values configured for outputs will only apply to workspaces **created** on that output.\n\nThe config can be reloaded at runtime with `layman reload`. Note that this reloads the config, but\nnot the layout managers. Config changes for existing layouts won't take affect until the managers is reset with\n`layman layout \u003clayout short name\u003e`.\n\n## Usage\n\nTo start using layman, simply run `layman`. This is best done in your sway/i3 config.\n\nTo send commands to layman, you can either bind `nop layman \u003ccommand\u003e` to a key, or execute `layman` again with arguments.\nYou could bind `exec layman \u003ccommand\u003e` to a key, but using `nop` is prefered to avoid overhead.\n\nCommands:\n```\nmove \u003cup|down|left|right\u003e # Passes movement to a WLM to handle, or back to sway/i3\nreload # Reloads config and user layouts\nlayout \u003clayout shortname\u003e # Sets a new layout on the focused workspace\n```\n\nLayouts may add their own commands, refer to the layouts below for more commands.\n\n## Layout Managers\n\nThe layout manager controlling a workspace can be changed using the command `nop layman layout \u003cLAYOUT\u003e`. In order to\nhandle window movement in layouts that don't use standard up/down/left/right, a WLM can override these commands with better\ndefaults, and layman will fall back the regular command for WLMs that don't. To use the WLM provided movement commands,\nreplace your `move \u003cdirection\u003e` bindsyms with\n```\n# Override move binds\nbindsym $mod+Shift+Left nop layman move left\nbindsym $mod+Shift+Down nop layman move down\nbindsym $mod+Shift+Up nop layman move up\nbindsym $mod+Shift+Right nop layman move right\n```\n\nThe `src/mananagers/` directoy contains files that each hold an implementation of a WLM, with `WorkspaceLayoutManager.py`\ncontaining the parent class from which all WLMs are derived.\n\n### none\n\nThe `none` layout manager does not manage any windows. It exists as a reference implementation, and to allow users\nto disable layout management on a given workspace.\n\nCommands:\n```\nlayman layout none # disable layout management on a workspace\n```\n\n### Autotiling\n\nBased on nwg-piotr's [autotiling](https://github.com/nwg-piotr/autotiling/blob/master/autotiling/main.py),\nthe `Autotiling` layout manager alternates between splith and splitv based on a windows height/width ratio.\n\nConfig options:\n```\ndepthLimit: Max number of nested splits [0 means no limit]\n```\n\nCommands:\n```\nlayman layout Autotiling # set focused workspace's layout manager to Autotiling\n```\n\n### Grid\n\n![](docs/Grid.gif)\n\nLike autotiling, Grid splits window based on width/height ratio. It differs from Autotiling by always splttting\nthe largest existing window, rather than the currently focused window. If multiple windows have the same size,\nGrid tries to split the left-most and top-most \"largest\" window. This results in a grid-like pattern.\n\nCommands:\n```\nlayman layout Grid # set focused workspace's layout manager to Grid\n```\n### MasterStack\n\n![](docs/MasterStack.gif)\n\n`MasterStack` is inspired by dwm/dwl/river, but is my own take on it. It implements a master window with a stack\non the side. When a new window is created, it replaces master and master is placed on top of the stack.\nIf the master window is deleted, the top of the stack replaces master. The layout of the stack container can be\n`splitv`, `tabbed`, or `stacking`. The layout of the stack can be toggled using a keybind.\n\n`MasterStack` also implements a keybind for swapping. When swapping, the focused window is swapped with master. If\nthe focused window is master, it gets swapped with the top of the stack. `MasterStack` also implements rotation.\nWhen rotating left, master is moved to the bottom of the stack, and the top of the stack becomes master.\nRotating right moves master to the top of the stack, and the bottom of the stack becomes master.\n\n`MasterStack` provides overrides for `move \u003cdirecton\u003e` binds. \n\nKnown bugs:\n-  Sometimes existing windows get missed when arranging an existing layout\n\nConfig options:\n```\nmasterWidth: Int to control the percent width of master window [1-99]\nstackLayout: String to control the layout of the stack [\"splitv\", \"tabbed\", \"stacking\"]\nstackSide: String to control which side of the screen the stack is on [\"right\", \"left\"]\n```\n\nCommands:\n```\nlayman layout MasterStack # set focused workspace's layout manager to MasterStack\nlayman swap master # swap focused window with master\nlayman rotate cw # rotate layout cw 1 window\nlayman rotate ccw # rotate layout ccw 1 window\nlayman move up # move focused winodw up 1 position in the stack\nlayman move down # move focused window down one position in the stack\nlayman stack toggle # toggles stack layout through splitv, tabbed, and stacking\nlayman stackside toggle # toggles stack side between left and right\n```\n\n### User Created Layouts\n\nYou can create layouts that get picked up and managed by layman without modifying layman itself. Any python file placed\nin the same directory as the config file will be automatically imported by layman at startup, and any time the\nconfiguration is reloaded. To get started writing your own layouts, take a look at `src/mangers/WorkspaceLayoutManger.py`\nin this repo. This is the base class from which your layout must inherit, and provides a number of hooks and functions\nfor handling window events. `src/managers/AutotilingLayoutManager.py` is a simple example of how to implement a WLM.\nWhen making a WLM, make sure that it has a unique shortname.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrap129%2Flayman","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrap129%2Flayman","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrap129%2Flayman/lists"}