{"id":43805440,"url":"https://github.com/frispete/wm-win-tool","last_synced_at":"2026-02-05T22:33:48.736Z","repository":{"id":62589319,"uuid":"244248795","full_name":"frispete/wm-win-tool","owner":"frispete","description":"Store and restore desktops, geometries and shaded state of selected X11 windows","archived":false,"fork":false,"pushed_at":"2022-01-21T13:20:34.000Z","size":85,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-03T20:13:34.163Z","etag":null,"topics":["firefox","session-management","x11"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frispete.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}},"created_at":"2020-03-02T00:48:04.000Z","updated_at":"2022-01-21T13:20:37.000Z","dependencies_parsed_at":"2022-11-03T17:51:15.287Z","dependency_job_id":null,"html_url":"https://github.com/frispete/wm-win-tool","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/frispete/wm-win-tool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frispete%2Fwm-win-tool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frispete%2Fwm-win-tool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frispete%2Fwm-win-tool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frispete%2Fwm-win-tool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frispete","download_url":"https://codeload.github.com/frispete/wm-win-tool/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frispete%2Fwm-win-tool/sbom","scorecard":{"id":411688,"data":{"date":"2025-08-11","repo":{"name":"github.com/frispete/wm-win-tool","commit":"edacf7a02a3b33f46ce55218e5e0d5b1c540594d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/23 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-18T22:51:39.795Z","repository_id":62589319,"created_at":"2025-08-18T22:51:39.795Z","updated_at":"2025-08-18T22:51:39.795Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29136789,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T21:59:57.939Z","status":"ssl_error","status_checked_at":"2026-02-05T21:59:57.628Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["firefox","session-management","x11"],"created_at":"2026-02-05T22:33:48.650Z","updated_at":"2026-02-05T22:33:48.728Z","avatar_url":"https://github.com/frispete.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"wm-win-tool\n===========\nStore desktops, geometries, and shade states of X11 windows, selected by\nwindow title and class patterns, in order to restore their layouts later on.\n\nThe primary reason for this program to exist is Firefox, that fails to restore\nits session properly under usual X11 window managers (KF5 in my case).\n\nNote, that the problem is well known, but unfortunately, little has been done\nin the last 13 years to [solve this issue](https://bugzilla.mozilla.org/show_bug.cgi?id=372650).\n\nThis program is an humble attempt to solve it manually/externally, but might\nprove useful for other constellations as well.\n\nUsage:\n------\n```\nwm-win-tool [-hVvfbr] [-c class][-t title] store\nwm-win-tool [-hVvfbr] [-c class][-t title] restore [arg]\nwm-win-tool [-hVvb][-c class][-t title] curlist [max]\nwm-win-tool [-hVv] list [max]\n       -h, --help           this message\n       -V, --version        print version and exit\n       -v, --verbose        verbose mode (cumulative)\n       -f, --force          force store\n       -b, --bracket        use the bracket pattern\n       -r, --regexp         class and title pattern are regexp\n       -c, --class class    match window class\n       -t, --title title    match window title\n```\n\nCommands\n--------\n`store` will save the geometry, desktop, and shaded state of selected windows\nby class or pattern, unless the previous state is unchanged or the operation\nis enforced with `--force`.\n\n`restore` will restore the window geometries, matched by class or pattern,\n`arg` is either a timestamp from the store list, or a relative index (eg. -1\nfor the latest session [default], -2 for the one before...).\n\nNote, that the selection parameters for store and restore *should* match.\n\nUse the `curlist` command to test your current selection options.\n\n`list` shows the available sessions up to an optional maximum number of items\nto be restored, sorted by date (descending).\n\nOptions\n-------\n`--class` and `--title` are simple case sensitive wildcard pattern, that can\nbe supplied multiple times to match a subset of windows. `--regexp` switches\nthem to regular expression matching. Make sure to properly quote such\narguments.\n\nThe `--bracket` option just matches the part of the window title in square\nbrackets, eg.: `[title] long title` will just match `[title]`. This is most\nuseful in conjunction with Firefox and the\n[Window Titler addon](https://github.com/tpamula/webextension-window-titler).\n\nExample Usage\n-------------\nCasual approach to restore your Firefox session:\n```\nwm-win-tool -vc Navigator.Firefox store\n```\nwill save every Firefox window, and\n```\nwm-win-tool -vc Navigator.Firefox restore\n```\nwill restore all recognized windows. The only downside is, that the window\ntitles must match **exactly** to be restored correctly. So better make sure to\nrun this tool right before leaving the session.\n\nA more robust approach to the issue in question: install the\n`Window Titler addon` and supply all windows, that you want to have managed\nwith a **unique** title, that appears in square brackets in front of the\nwindow title. This provides a static title, independent from which tab is\nactived.\n\nNow saving a session is as easy as:\n```\nwm-win-tool -vb store\n```\n\nYou can run this command as many times as you want. As long as the session\nwasn't changed meanwhile, it won't store a new session (unless the `--force`\noption is supplied).\n\nAfter reboot, you may wish to restore this session:\n```\nwm-win-tool -vb restore\n```\né voila, the windows move to their original desktops, and have their former\ngeometry and shaded state applied.\n\nInstall\n-------\nUsing pip:\n```\n$ pip install wm-win-tool\n```\n\nFrom source:\n```\n$ wget https://files.pythonhosted.org/packages/source/w/wm-win-tool/wm-win-tool-\u003cversion\u003e.tar.gz\n$ tar xvf wm-win-tool-\u003cversion\u003e.tar.gz\n$ cd wm-win-tool-\u003cversion\u003e\n$ python3 setup.py install\n```\n\nDependencies\n------------\nYou need to make sure, that the command line programs `wmctrl` and `xprop` are\ninstalled. Check with your distributions package manager..\n\nConsequently, `wm-win-tool` needs a proper DISPLAY/XAUTHORITY environment\nsetup.\n\nFinal notes\n-----------\nThere are good chances, that the Firefox issue is fixed with Version 75. Hooray.\nLet's hope for the best. If all goes well, this tool provides a nice way to\n**validate** the final fix. If all windows match, it will not perform any action\non (verbose) restore. :wink:\n\nThe commands `store` and `restore` could be implicitly triggered, when executed\nvia symlinks to `wm-win-tool`, eg.:\n```\n$ cd \u003cwhatever\u003e/bin\n$ ln -s wm-win-tool wm-win-store\n$ ln -s wm-win-tool wm-win-restore\n```\nThese operation modes come with some hardcoded defaults: `--bracket` and\n`--verbose` for the most usual usage patterns. If that's not enough, a config\nfile option might be useful (TBD).\n\nThe session data is saved in `~/local/share/wm-win-tool`.\n\nIn pathological cases (where I count in for sure), it might be advantageous\nto exclude Firefox from the window manager session restore completely. kwin5\nis configurable as such. When executing Firefox after reboot, it will open all\nsession windows on your **current** desktop then. Run `wm-win-restore` and *be\ndone*.\n\nIf you plan to run `wm-win-store` from `crontab -e`, keep in mind, that most\ncron implementations suffer from variable expansion issues. Here is an\nexample, that should work with Vixie cron:\n```\n#PATH=$HOME/bin:/bin:/usr/bin\t# won't work\n#XAUTHORITY=~/.Xauthority\t# neither that\n\n# store firefox window list\n42 * * * * XAUTHORITY=~/.Xauthority DISPLAY=:0 wm-win-tool -b store\n```\n`AUTHORITY`is expanded from the shell in this case, which is necessary to\noperate properly. Depending on the way, you installed `wm-win-tool`, you might\nneed to adjust the path as well. We also avoid using the symlink shortcut\nhere due to its implicit verbosity level.\n\nSome things are realized in a pretty `oldschool` way, eg. command line\nhandling, but until the command line interface gets **significantly** more\ncomplex, I prefer to do it this way (since ages).\n\nIf you have other ideas, interesting applications, what ever, let me know.\n\nFeedback welcome.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrispete%2Fwm-win-tool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrispete%2Fwm-win-tool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrispete%2Fwm-win-tool/lists"}