pax_global_header00006660000000000000000000000064145777604020014526gustar00rootroot0000000000000052 comment=8182ffdff2b838e46c31dd4366b7ea4fe22818dd Tiling-Assistant-46/000077500000000000000000000000001457776040200145165ustar00rootroot00000000000000Tiling-Assistant-46/.eslintrc.json000066400000000000000000000174051457776040200173210ustar00rootroot00000000000000// Based on https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/blob/main/lint/eslintrc-gjs.yml#L67 { "env": { "es6": true, "es2020": true }, "extends": "eslint:recommended", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "rules": { "array-bracket-newline": [ "error", "consistent" ], "array-bracket-spacing": [ "error", "never" ], "array-callback-return": "error", "arrow-parens": [ "error", "as-needed" ], "arrow-spacing": "error", "block-scoped-var": "error", "block-spacing": "error", "comma-dangle": "error", "comma-spacing": [ "error", { "before": false, "after": true } ], "comma-style": [ "error", "last" ], "computed-property-spacing": "error", "curly": [ "error", "multi-or-nest", "consistent" ], "dot-location": [ "error", "property" ], "eol-last": "error", "eqeqeq": "error", "func-call-spacing": "error", "func-name-matching": "error", "func-style": [ "error", "declaration", { "allowArrowFunctions": true } ], "indent": [ "error", 4, { "FunctionExpression": { "parameters": 2 }, "SwitchCase": 1, "ignoredNodes": ["CallExpression[callee.object.name=GObject][callee.property.name=registerClass] > ClassExpression:first-child"], "MemberExpression": "off" } ], "key-spacing": [ "error", { "beforeColon": false, "afterColon": true } ], "keyword-spacing": [ "error", { "before": true, "after": true } ], "linebreak-style": [ "error", "unix" ], "max-nested-callbacks": "error", "max-statements-per-line": [ "error", { "max": 2 } ], "new-parens": "error", "no-array-constructor": "error", "no-await-in-loop": "error", "no-caller": "error", "no-constant-condition": [ "error", { "checkLoops": false } ], "no-div-regex": "error", "no-empty": [ "error", { "allowEmptyCatch": true } ], "no-extra-bind": "error", "no-extra-boolean-cast": "off", "no-extra-parens": [ "error", "all", { "conditionalAssign": false, "nestedBinaryExpressions": false, "returnAssign": false } ], "no-implicit-coercion": [ "error", { "allow": ["!!"] } ], "no-iterator": "error", "no-label-var": "error", "no-lonely-if": "error", "no-loop-func": "error", "no-multiple-empty-lines": "error", "no-multi-spaces": "error", "no-nested-ternary": "error", "no-new-object": "error", "no-new-wrappers": "error", "no-octal-escape": "error", "no-proto": "error", "no-prototype-builtins": "off", "no-restricted-properties": [ "error", { "object": "imports", "property": "format", "message": "Use template strings" }, { "object": "pkg", "property": "initFormat", "message": "Use template strings" }, { "object": "Lang", "property": "copyProperties", "message": "Use Object.assign()" }, { "object": "Lang", "property": "bind", "message": "Use arrow notation or Function.prototype.bind()" }, { "object": "Lang", "property": "Class", "message": "Use ES6 classes" } ], "no-return-assign": "error", "no-return-await": "error", "no-self-compare": "error", "no-shadow": "error", "no-shadow-restricted-names": "error", "no-spaced-func": "error", "no-tabs": "error", "no-template-curly-in-string": "error", "no-throw-literal": "error", "no-trailing-spaces": "error", "no-undef": "error", "no-unneeded-ternary": "error", "no-unused-vars": [ "error", { "vars": "local", "varsIgnorePattern": "(^unused|_$)", "argsIgnorePattern": "^(unused|_)" } ], "no-useless-call": "error", "no-useless-computed-key": "error", "no-useless-concat": "error", "no-useless-constructor": "error", "no-useless-rename": "error", "no-useless-return": "error", "no-whitespace-before-property": "error", "no-with": "error", "nonblock-statement-body-position": [ "error", "below" ], "object-curly-newline": [ "error", { "consistent": true, "multiline": true } ], "object-curly-spacing": [ "error", "always" ], "object-shorthand": "error", "operator-assignment": "error", "operator-linebreak": "error", "padded-blocks": [ "error", "never" ], "prefer-numeric-literals": "error", "prefer-promise-reject-errors": "error", "prefer-rest-params": "error", "prefer-spread": "error", "prefer-template": "error", "quotes": [ "error", "single", { "avoidEscape": true } ], "require-await": "error", "rest-spread-spacing": "error", "semi": [ "error", "always" ], "semi-spacing": [ "error", { "before": false, "after": true } ], "semi-style": "error", "space-before-blocks": [ "error", "always" ], "space-before-function-paren": [ "error", { "named": "never", "anonymous": "always", "asyncArrow": "always" } ], "space-in-parens": "error", "space-infix-ops": [ "error", { "int32Hint": false } ], "space-unary-ops": "error", "switch-colon-spacing": "error", "symbol-description": "error", "template-curly-spacing": "error", "template-tag-spacing": "error", "unicode-bom": "error", "wrap-iife": [ "error", "inside" ], "yield-star-spacing": "error", "yoda": "error" }, "globals": { "ARGV": "readonly", "Debugger": "readonly", "GIRepositoryGType": "readonly", "globalThis": "readonly", "global": "readonly", "imports": "readonly", "Intl": "readonly", "log": "readonly", "logError": "readonly", "print": "readonly", "printerr": "readonly", "window": "readonly", "TextEncoder": "readonly", "TextDecoder": "readonly" } } Tiling-Assistant-46/.github/000077500000000000000000000000001457776040200160565ustar00rootroot00000000000000Tiling-Assistant-46/.github/ISSUE_TEMPLATE/000077500000000000000000000000001457776040200202415ustar00rootroot00000000000000Tiling-Assistant-46/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000007311457776040200227340ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: bug assignees: '' --- **Describe the bug** **Steps To Reproduce** **System Info:** - Distro (incl. version): - GNOME Shell version: - Extension version and from where (e. g. EGO, `main` branch...): - XOrg/Wayland: **Journalctl logs** Tiling-Assistant-46/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000010441457776040200237650ustar00rootroot00000000000000--- name: Feature request about: Suggest a new feature title: '' labels: enhancement assignees: '' --- **Briefly describe how the feature should work** **Explain why this feature should be added** Tiling-Assistant-46/.github/ignore-words.txt000066400000000000000000000001441457776040200212350ustar00rootroot00000000000000allws Distro fullscreen gettext Journalctl journalctl leleat Msgid msgid msgstr prefs Rects UntilingTiling-Assistant-46/.github/workflows/000077500000000000000000000000001457776040200201135ustar00rootroot00000000000000Tiling-Assistant-46/.github/workflows/create-release.yml000066400000000000000000000012241457776040200235160ustar00rootroot00000000000000name: Release run-name: Create Release on: push: tags: - "v*" jobs: release: name: Create release runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: sudo apt-get update -q && sudo apt-get install gettext - run: bash scripts/build.sh - uses: svenstaro/upload-release-action@2.5.0 with: file: tiling-assistant@leleat-on-github.shell-extension.zip overwrite: true release_name: Tiling Assistant ${{ github.ref_name }} body: "Read about all the changes [here](https://github.com/Leleat/Tiling-Assistant/blob/main/CHANGELOG.md#${{ github.ref_name }})." Tiling-Assistant-46/.github/workflows/run-ci.yml000066400000000000000000000037341457776040200220420ustar00rootroot00000000000000name: CI run-name: Check ${{ github.ref_name }} by @${{ github.actor }} on: pull_request jobs: linters: name: Run linters runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - uses: actions/setup-node@v3 with: node-version: "*" - name: Prepare Linters run: npm install -g eslint stylelint stylelint-config-standard - name: Run ESLint (*.js) run: > git diff --name-only --diff-filter=ACMTUXB origin/${{ github.base_ref }} HEAD | grep -E "\.js$" | xargs -r eslint - name: Run stylelint (*.css) if: success() || failure() run: > git diff --name-only --diff-filter=ACMTUXB origin/${{ github.base_ref }} HEAD | grep -E "\.css$" | xargs -r stylelint - name: Run ShellCheck (*.sh) if: success() || failure() run: > git diff --name-only --diff-filter=ACMTUXB origin/${{ github.base_ref }} HEAD | grep -E "\.sh$" | xargs -r shellcheck spellcheck: name: Run spell check runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - uses: actions/setup-node@v3 with: node-version: "*" - run: pip install codespell # The case sensitivity of codespeller for ignore-words seems to be buggy. See # issue tracker. According to the help page it should be case sensitive but # only 'allws' makes codespeller ignore 'allWs' in code files. - name: Run codespell run: > git diff --name-only --diff-filter=ACMTUXB origin/${{ github.base_ref }} HEAD | xargs -r codespell -q 3 --skip="*.po*,*.git/*" --ignore-words .github/ignore-words.txt build: name: Run build runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: sudo apt-get update -q && sudo apt-get install gettext - run: bash scripts/build.sh Tiling-Assistant-46/.gitignore000066400000000000000000000000541457776040200165050ustar00rootroot00000000000000locale/ gschemas.compiled *.zip *~ TODO.txt Tiling-Assistant-46/.stylelintrc.yml000066400000000000000000000002431457776040200176720ustar00rootroot00000000000000extends: stylelint-config-standard rules: # modern and percentage not supported under g-s color-function-notation: legacy alpha-value-notation: number Tiling-Assistant-46/CHANGELOG.md000066400000000000000000000307161457776040200163360ustar00rootroot00000000000000# Changelog ## [44] - 2023-09-18 ### Added - support for GNOME 45 (#281) ## [43] - 2023-09-17 ### Fixed - Window not resizing correctly when it enters another monitor - by domferr (#290) ## [42] - 2023-09-03 ### Added - Italian translation by albanobattistella (#271) ### Fixed - Move modes update correctly when the grabbed window changes the monitor (#279) ## [41] - 2023-05-17 ### Fixed - Tiling Popup not appearing under some circumstances (#259) - Properly restore tiling props on all workspaces (#262) ## [40] - 2023-04-13 ### Added - Support for GNOME Shell 44 by 3v1n0 (mostly #234) - Github CI: linting and spell checking - Spanish translations by IngrownMink4 (#216) - Dutch translations by flipflop97 (#215) - Italian translations by albanobattistella (#220) - German translations by affengeist (#231) - Hungarian translations by infeeeee (#236) ### Fixed - The position of the fix-search-a-layout popup now appears correctly on multi-monitor setups (#247) - Fix tiling when there are always-on-top windows (#240) - Fix non-extension maximization window-restore position (#251) ### Changed - Move UserGuide.MD into the [github wiki](https://github.com/Leleat/Tiling-Assistant/wiki) - Update Scripts and a bugfix by SubOptimal (#248, #249, #250) ## [39] - 2022-11-23 ### Fixed - Clean up settings signals properly (technically only relevant for the active hint since it may be destroyed before the settings singleton) ## [38] - 2022-11-23 ### Fixed - Issue with always active window hint (there is still a problem with GTK4 popups on Wayland) ## [37] - 2022-11-22 ### Added - Added active window hint. By default the `Minimal` option will be chosen (#210) - Added an option to not use T-A features (Tiling Popup and grouping) when DNDing a window via a modifier and via additional keyboard shortcuts. Features are hidden behind the advanced settings (#212) - Added setting for a single/uniform screen gap instead of splitting it into edges (each edge is still available, if the advanced settings are enabled) ### Changed - Increased possible maximum of gaps to 500 (#205) - Changed/shuffled some of the preferences around ## [36] - 2022-09-04 ### Added - Support GNOME 43 ### Changed - Removed the 'row'-look of shortcuts in the layouts ### Fixed - Consider monitor scale when calculating window gaps (#196) ## [35] - 2022-07-23 ### Added - Added setting to disable multi-monitor grace period (#189) ### Changed - Make the 'improved performance behavior' opt-in (in the advanced settings) since it impacts the precision of the tile preview (#190) ### Fixed - Fixed issue about windows maximizing to wrong monitor under some circumstances setups (#188) ### Removed - Removed in-app changelog ## [34] - 2022-07-13 ### Added - Added setting to completely disable tile groups. That means no resizing, raising or suggestions anymore (#180) - Added the ability to only resize the absolutely necessary windows in a tile group when holding `Ctrl` before resizing started (#155) ### Changed - Improved performance when dragging a window around for lower performance machines (#181) - Split the screen gap setting into top, bottom, left and right parts by CharlieQLe (#146) - Don't open the changelog window after an extension update in the prefs by default anymore ### Fixed - Added a workaround for a multi-monitor bug where windows may untile incorrectly under Wayland (#137) - Fixed issue with RMB as a `Move Mode Activator` under Wayland (#170) - Added Meta as a `Move Mode Activator` and set it as default, if `Alt` is the default window action key (#172) ## [33] - 2022-05-07 ### Added - German (Switzerland) tl by MrReSc #152 - German (Germany) tl by pjanze #161 - Italian translation by starise #164 - Spanish translation by fjsevilla-dev #168 ### Changed - Port to GNOME 42 and drop support for older versions - Brazilian Portuguese tl by ItzJaum #157 - If an app is attached to a layout rect, try to tile an existing window instance first before opening a new one ### Removed - Deprecate 'App Switcher and Tiling Popup' setting - Hacky partial touch 'support' ### Fixed - Override GNOME's default shortcuts only if they are set in Tiling Assistant ## [32] - 2022-01-22 ### Added - Added new keyboard shortcuts: - Restore window size (#134) - Toggle Vertical Maximization - Toggle Horizontal Maximization - Move Window to Center (#132) - Toggle `Always on Top` - Added ability to move tile groups to a new workspace/monitor using the Tile Editing Mode: - `Shift`+`Directions` moves the tile group to a new monitor - `Shift`+`Alt`+`Directions` moves the tile group to a new workspace - Tiled windows will untile themselves if they change workspaces - Allow one action to have multiple keyboard shortcuts (press `Enter` or `Space` when listening for a new keyboard shortcut to append shortcuts to existing ones) - Added GNOME's native tiling behavior (`Super`+`Up`/`Down`/`Left`/`Right`) to the default shortcuts ### Changed - Adapt edge-tiling only if it doesn't cover existing tiles. Use `Ctrl`-drag (mouse) or the `Tile Editing Mode` (keyboard) to 'replace/cover' existing tiles. That way 1 window can be part of multiple tile groups - Reworked tile group detection when a window is tiled - Renamed `Split Tiles` mode to `Adaptive Tiling`. This is the mode when moving a window around while holding `Ctrl` - Disabled grouping tiled windows in the app switcher by default and mark that setting as experimental - Introduce concept of deprecated settings and deprecate the `Toggle Tiling Popup` and `Auto-Tile` keyboard shortcuts - Deprecated settings won't be visible in the prefs window anymore unless they have a non-default value set ### Fixed - Fixed a compatibility issue introduced in v31 with other alt-Tab extensions (#126) - Fixed the Tiling Popup ignoring the Tile Group setting `App Switcher and Tiling Popup` - Shortcuts may no longer change unintentionally after using the clear-shortcut-button - Fixed the URLs in the prefs' popup menu freezing the prefs - Wayland only (#136) ## [31] - 2021-12-10 ### Fixed - Fixed crash introduced in v28 (#125) ## [30] - 2021-12-10 ### Fixed - Fixed crash introduced in v28 (#124) ## [29] - 2021-12-09 ### Fixed - Removed timer sources according to EGO review ## [28] - 2021-12-09 ### Added - Added a Panel Indicator for the layouts (disabled by default). With it you can activate a layout with your pointer or change your `Favorite Layout` (per monitor) - Added a setting to group tileGroups in the AppSwitcher (altTab) and Tiling Popup - When dnd-ing a window, hold `Super` to make the tile preview span multiple rectangles. This only works in the `Favorite Layout` or `Split Tiles` preview modes - Added a `hidden` setting to not adapt the Edge-Tiling to the favorite layouts ### Removed - Removed the `Change favorite layouts` keyboard shortcut (Use the Panel Indicator instead) - Removed the favorite button from the `Layouts` in the preferences (Use the Panel Indicator instead) ### Changed - Show the entire Layout when moving a window with the `Favorite Layout` preview mode - Updated the jp translation (by k-fog #112) - Untile tiled windows, if they are moved to a new monitor or workspace (#114) - `Tile Editing Mode`: Pressing `Space` will always open the Tiling Popup (even if there is already a window in that spot) - Visual tweaks to the preference window ### Fixed - When dragging a window to a new monitor there is a short `Grace Period` (150 ms), in which, if the grab is released, the window will tile to the old monitor. Fix: The `Tiling Popup` will appear on the correct monitor now. - Fixed artifacts due to the rounded corners of the `Changelog Dialog` (only works on Wayland) - Fixed animations being skipped, if an animation was already running (#58) ## [27] - 2021-11-01 ### Added - `Favorite Layout`, a new window movement mode, as an alternative to the default Edge Tiling (issue #94) - It allows users to dnd a window to a predefined layout (Check out the `GUIDE.md` for details) - It also adapts the keyboard shortcuts and edge previews to the favorite layout - Changelog dialog to prefs window on new extension version (deactivatable in `Hidden Settings`) ### Removed - The color selection for the Tile Editing Mode because now we can always follow the system's native Tile-Preview style ### Changed - Split gaps into `Window Gaps` and `Screen Gaps` (i. e. when windows are touching the screen edges) (discussion #109) - `Tile to top` & `Toggle Maximization` cycle between top tiling and maximization in `Tiling State` and `Tiling State (Windows)` - Reworked the preference window to follow GNOME's HIG a bit more closely - Moved the `Inverse Top Screen Edge Action` settings to the `Hidden Setting` - Moved the `Include apps from all workspaces` for the Tiling Popup to the general settings - And some other minor settings tweaks ## [26] - 2021-10-14 ### Added - AUR package (not by me, see #85) ### Changed - Hid the `Layouts` behind the 'Advanced / Experimental Settings' switch (in `Hidden Settings`) - Renamed `Layout` to `Popup Layout` since just `Layout` may be misleading - Tile Editing Mode's resizing now follows GNOME native keyboard resizing style (see `Alt` + `F8`) - Removed the PieMenu - Removed support for GNOME < 40 - Refactored code & created scripts to automate stuff like building, updating translations... ## [25] - 2021-09-27 ### Fixed - Bug when PieMenu is enabled ## [24] - 2021-09-27 ### Added - Clear-keybindings button - Dutch translation (by Vistaus #95) - Partial japanese translation (by k-fog #89) - Added Brazilian Portuguese translation (by msmafra #92) - Windows-like minimize option for the dynamic keybindings - Hidden settings: choose secondary mode (tile preview) activator and option to default to secondary mode (#90) ### Fixed - GNOME Shell 41: use new function, which got replaced in GS ## [23] ### Added - Partial Traditional Chinese translation for users in Taiwan (by laichiaheng #84) - Added dynamic tiling options: disabled, focus & tiling states (#87) - Added the 'layout selector' as an option for the pieMenu ### Changed - Moved 'Tile Editing Mode: Focus Color' to the 'Hidden Settings' - Removed experimental semi-autotiling mode (#70) - Simplify tl file (removed duplicates) ### Fixed - Multimonitor: wrong position for the focus indicator of the tile editing mode - Multimonitor: wrong position for the layout selector - Multimonitor: inconsistent behavior for tiling a window via DND within the 'grace period' ## [22] ### Added - Link to a list of known incompatible apps/extensions (github issue #61) - Czech translation (by pervoj #81) ### Fixed - Correctly position PieMenu on multimonitor setup (#78) - Wrong tilePreview, if window was at the very top display edge - Stop an extension crash, if ~/.config/tiling-assistant didn't exist, when the screen got locked (#80) ## [21] ### Fixed - Re-enable focus on prefs40.ui - Correctly use pointer position when moving window with keyboard `Alt` + `F7` + `Arrow` keys (#76) ## [20] ### Added - Tile Editing Mode: add option to 'equalize' window sizes (see 6bfbc07) - Layouts: add dynamic rectangles to enable layouts like Master & Stack (see the tooltip in the `Layouts` tab of the settings) - Experimental: Semi Tiling Mode (see 'Hidden Settings') - Setup `translations/` for translations ### Changed - Remove `User Guide` and `Changelog` tabs from the settings page (instead create .md files in repo) ### Fixed - Restore tile states properly after a screen lock ## [17] - [19] ### Added - Experimental: app attachments to layouts ### Changed - Layouts: move layouts file from the extension folder to $XDG_CONFIG_HOME/tiling-assistant/layouts.json (#68) ### Fixed - Raise tileGroups with sloppy mouse focus mode only on click ## [16] ### Added - Pie menu: Super + RMB a window - Settings: gaps on maximized windows (off by default) - Settings: 'restore window size on grab end' (workaround for Wayland) - Experimental: Tile Editing Mode ## [13] - [15] ### Added - Dynamic tiling ('focus and tiling') - Ctrl-dragging a window now also works for multiple windows (by dragging the window to the very edges of other windows/free screen rects) - Inverse top screen edge action (by c-ridgway) - Multi-monitor: the tile preview will stick to the old monitor when changing monitors for a short period to easier tile quickly on the old monitor (by c-ridgway) - Default keybindings with the numpad for tiling (by c-ridgway) - Dynamic numbers of layouts & layout selector - Add 'User Guide' and 'Changelog' settings tab ### Changed - Other minor settings additions/removals/changes Tiling-Assistant-46/LICENSE000066400000000000000000000432541457776040200155330ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. Tiling-Assistant-46/README.md000066400000000000000000000042121457776040200157740ustar00rootroot00000000000000# Tiling Assistant Tiling Assistant is a GNOME Shell extension which adds a Windows-like snap assist to the GNOME desktop. It expands GNOME's 2 column tiling layout and adds many more features. ## Features Please visit the [wiki](https://github.com/Leleat/Tiling-Assistant/wiki) for a list of all features. You'll also find videos and explanations for each of them there. ## Supported GNOME Versions The [metadata](https://github.com/Leleat/Tiling-Assistant/blob/main/tiling-assistant%40leleat-on-github/metadata.json#L4) file lists all currently supported GNOME Shell versions. Generally, only the most recent GNOME Shell is supported. That means older releases may not include all features and bug fixes. You can look at the revisions of the wiki articles to find out when a feature was added, changed, or improved. The [changelog](https://github.com/Leleat/Tiling-Assistant/blob/main/CHANGELOG.md) will show all changes in chronological order. Here is a table showing the GNOME Shell releases and the latest extension version supporting them. | GNOME Shell | Tiling Assistant | |:-------------:|:-----------:| | 45 | 44 | | 44 | 43 | | 43 | 43 | | 42 | 36 | | 41 | 32 | | 40 | 32 | | 3.38 | 23 | | 3.36 | 23 | ## Installation You can install it via https://extensions.gnome.org/extension/3733/tiling-assistant/. Alternatively, or if you want an up-to-date version, download / clone the repository and run the `scripts/build.sh` script with the `-i` flag. Make sure to have `gettext` installed. If you've manually installed the extension, you need to reload GNOME Shell afterwards (e.g. by logging out). It's also on the AUR but that repository is maintained by a 3rd party. ## Translation Translations are welcome! If you are already familiar with how it works, feel free to directly open a pull request with a `YOUR_LANG.po` file at `translations/`. Don't worry, in case you don't know how to create a `.po` file. Just open an issue and I'll set everything up. You'll only need a text editor and your language skills 🙂. ## License This extension is distributed under the terms of the GNU General Public License, version 2 or later. See the license file for details. Tiling-Assistant-46/scripts/000077500000000000000000000000001457776040200162055ustar00rootroot00000000000000Tiling-Assistant-46/scripts/aur-build/000077500000000000000000000000001457776040200200715ustar00rootroot00000000000000Tiling-Assistant-46/scripts/aur-build/.SRCINFO000066400000000000000000000011021457776040200211670ustar00rootroot00000000000000pkgbase = gnome-shell-extension-tiling-assistant pkgdesc = A GNOME Shell extension to expand GNOME's native 2 column design. pkgver = 46 pkgrel = 1 url = https://github.com/Leleat/Tiling-Assistant install = INSTALL arch = x86_64 license = GPL2 makedepends = gettext depends = gnome-shell provides = gnome-shell-extension-tiling-assistant conflicts = gnome-shell-extension-tiling-assistant source = gnome-shell-extension-tiling-assistant::git+https://github.com/Leleat/Tiling-Assistant.git#tag=v46 sha256sums = SKIP pkgname = gnome-shell-extension-tiling-assistant Tiling-Assistant-46/scripts/aur-build/INSTALL000066400000000000000000000021231457776040200211200ustar00rootroot00000000000000## arg 1: the new package version post_install() { echo "" echo ------------------------------------------------------------------------------- echo Reload GNOME Shell and enable the extension to finish the installation process. echo ------------------------------------------------------------------------------- echo } ## arg 1: the new package version ## arg 2: the old package version post_upgrade() { echo "" echo ------------------------------------------------- echo Reload GNOME Shell to finish the upgrade process. echo ------------------------------------------------- echo } ## arg 1: the old package version post_remove() { echo "" echo --------------------------------------------------------- echo Reload GNOME Shell to finish the uninstallation process. echo "" echo If you didn\'t disable the extension before removal, run echo "'gsettings set org.gnome.mutter edge-tiling true ; \\" echo gsettings set org.gnome.shell.overrides edge-tiling true\' echo to re-enable GNOME\'s native edge tiling. echo --------------------------------------------------------- echo } Tiling-Assistant-46/scripts/aur-build/PKGBUILD000066400000000000000000000022731457776040200212210ustar00rootroot00000000000000# Maintainer: Leleat # Contributor: VeldoraTheDragon <127216238+VeldoraTheDragon@users.noreply.github.com> pkgname=gnome-shell-extension-tiling-assistant pkgver=46 pkgrel=1 pkgdesc="A GNOME Shell extension to expand GNOME's native 2 column design." arch=('x86_64') url="https://github.com/Leleat/Tiling-Assistant" license=('GPL2') depends=('gnome-shell') install='INSTALL' makedepends=('gettext') provides=("${pkgname}") conflicts=("${pkgname}") source=("${pkgname}::git+https://github.com/Leleat/Tiling-Assistant.git#tag=v${pkgver}") sha256sums=('SKIP') _uuid="tiling-assistant@leleat-on-github" prepare() { install -dm755 "${srcdir}/${pkgname}/${_uuid}/locale" } build() { cd "${srcdir}/${pkgname}/${_uuid}" # compile gschema glib-compile-schemas ./schemas/ # compile tl for FILE in ${srcdir}/${pkgname}/translations/*.po; do LANG=$(basename "$FILE" .po) mkdir -p "${srcdir}/${pkgname}/${_uuid}/locale/$LANG/LC_MESSAGES" msgfmt -c "$FILE" -o "${srcdir}/${pkgname}/${_uuid}/locale/$LANG/LC_MESSAGES/${_uuid}.mo" done } package() { install -dm755 "${pkgdir}/usr/share/gnome-shell/extensions" cp -r "${srcdir}/${pkgname}/${_uuid}" "${pkgdir}/usr/share/gnome-shell/extensions/${_uuid}" } Tiling-Assistant-46/scripts/build.sh000077500000000000000000000025451457776040200176510ustar00rootroot00000000000000#!/bin/bash # exit, if a command fails set -e # cd to repo dir SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" cd "$SCRIPT_DIR"/../ # compile settings glib-compile-schemas tiling-assistant@leleat-on-github/schemas # compile tl: requires gettext for FILE in translations/*.po; do LANG=$(basename "$FILE" .po) mkdir -p "tiling-assistant@leleat-on-github/locale/$LANG/LC_MESSAGES" msgfmt -c "$FILE" -o "tiling-assistant@leleat-on-github/locale/$LANG/LC_MESSAGES/tiling-assistant@leleat-on-github.mo" done # create zip package and delete locale directory rm -f tiling-assistant@leleat-on-github.shell-extension.zip cd tiling-assistant@leleat-on-github zip -qr tiling-assistant@leleat-on-github.shell-extension.zip ./* cd .. mv tiling-assistant@leleat-on-github/tiling-assistant@leleat-on-github.shell-extension.zip ./ while getopts i FLAG; do case $FLAG in i) echo Installing extension... gnome-extensions install --force tiling-assistant@leleat-on-github.shell-extension.zip && \ rm -f tiling-assistant@leleat-on-github.shell-extension.zip && \ echo Installation complete. Restart GNOME Shell and enable the extension to use it. || \ exit 1;; *) echo Don\'t use any flags to just create an extension package. Use \'-i\' to additionally install the extension. exit 1;; esac done Tiling-Assistant-46/scripts/release.sh000077500000000000000000000025531457776040200201710ustar00rootroot00000000000000#!/bin/bash # exit, if a command fails set -e # cd to repo dir SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" cd "$SCRIPT_DIR"/../ METADATA=tiling-assistant@leleat-on-github/metadata.json # get new version nr VERSION_LINE=$(cat $METADATA | grep \"version\":) # split after ":" and trim the spaces VERSION_NR=$(echo "$VERSION_LINE" | cut -d ':' -f 2 | xargs) NEW_VERSION_NR=$((VERSION_NR + 1)) # switch to new release branch git checkout -b "release-$NEW_VERSION_NR" # bump up version nr in metadata.json echo Updating metadata.json... sed -i "s/\"version\": $VERSION_NR/\"version\": $NEW_VERSION_NR/" $METADATA echo Metadata updated. echo # bump up version nr in AUR files PKGBUILD=scripts/aur-build/PKGBUILD echo Updating Arch\'s PKGBUILD... sed -i "s/pkgver=$VERSION_NR/pkgver=$NEW_VERSION_NR/" $PKGBUILD cd scripts/aur-build/ makepkg --printsrcinfo > .SRCINFO cd ../../ echo PKGBUILD updated. echo # update translations bash scripts/update-tl.sh echo # package zip for EGO bash scripts/build.sh # commit changes echo Committing version bump... git add $METADATA $PKGBUILD CHANGELOG.md scripts/aur-build/.SRCINFO translations/*.po translations/*.pot git commit -m "Release: Bump version to $NEW_VERSION_NR" echo echo Release done. echo echo TODO: echo echo [] Push release branch and and create pull request echo [] Create and push tag echo [] Upload the extension to EGO Tiling-Assistant-46/scripts/update-tl.sh000077500000000000000000000007371457776040200204520ustar00rootroot00000000000000#!/bin/bash # exit, if a command fails set -e # cd to repo dir SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" cd "$SCRIPT_DIR"/../ # update main.pot echo -n Updating \'translations/main.pot\' xgettext \ --from-code=UTF-8 \ --output=translations/main.pot \ ./*/*/*/*.ui ./*/*.js ./*/*/*.js ./*/*/*/*.js echo \ ......... done. # update .po files for FILE in translations/*.po; do echo -n "Updating '$FILE' " msgmerge -NU "$FILE" translations/main.pot done Tiling-Assistant-46/tiling-assistant@leleat-on-github/000077500000000000000000000000001457776040200231745ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/extension.js000066400000000000000000000324141457776040200255520ustar00rootroot00000000000000/* extension.js * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-2.0-or-later */ import { Gio, GLib, Meta } from './src/dependencies/gi.js'; import { Extension, Main } from './src/dependencies/shell.js'; import MoveHandler from './src/extension/moveHandler.js'; import ResizeHandler from './src/extension/resizeHandler.js'; import KeybindingHandler from './src/extension/keybindingHandler.js'; import LayoutsManager from './src/extension/layoutsManager.js'; import ActiveWindowHint from './src/extension/activeWindowHint.js'; import AltTabOverride from './src/extension/altTab.js'; import { Rect } from './src/extension/utility.js'; /** * 2 entry points: * 1. keyboard shortcuts: * => keybindingHandler.js * 2. Grabbing a window: * => moveHandler.js (when moving a window) * => resizeHandler.js (when resizing a window) */ class SettingsOverrider { constructor(settingsSingleton) { this._settings = settingsSingleton; this._overrides = new Map(); this._originalSettings = new Map(); this._maybeNullValue = GLib.Variant.new_maybe( new GLib.VariantType('b'), null); const savedSettings = this._settings.getUserValue('overridden-settings'); this._wasOverridden = savedSettings !== null; } _maybeUpdateOverriden(schemaId, key, value) { if (this._wasOverridden) return undefined; const savedSettings = this._settings.getValue( 'overridden-settings').deepUnpack(); const prefKey = `${schemaId}.${key}`; const oldValue = savedSettings[prefKey]; if (value !== undefined) savedSettings[prefKey] = value ?? this._maybeNullValue; else delete savedSettings[prefKey]; this._settings.setValue('overridden-settings', new GLib.Variant('a{sv}', savedSettings)); return oldValue; } add(settings, key, value) { this._originalSettings.set(settings.schemaId, settings); const userValue = settings.get_user_value(key); const values = this._overrides.get(settings.schemaId) ?? new Map(); if (!values.size) this._overrides.set(settings.schemaId, values); values.set(key, userValue); settings.set_value(key, value); this._maybeUpdateOverriden(settings.schemaId, key, userValue ?? this._maybeNullValue); } remove(schema, key) { const settings = this._originalSettings.get(schema); if (!settings) return; const values = this._overrides.get(settings.schemaId); const value = values?.get(key); if (value === undefined) return; if (value) settings.set_value(key, value); else settings.reset(key); values.delete(key); this._maybeUpdateOverriden(settings.schemaId, key, undefined); } _clear() { if (this._wasOverridden) { const savedSettings = this._settings.getValue( 'overridden-settings').unpack(); Object.entries(savedSettings).forEach(([path, value]) => { const splits = path.split('.'); const key = splits.at(-1); const schemaId = splits.slice(0, -1).join('.'); const settings = this._originalSettings.get(schemaId) ?? new Gio.Settings({ schema_id: schemaId }); value = value.get_variant(); if (value.equal(this._maybeNullValue)) settings.reset(key); else settings.set_value(key, value); }); } else { this._originalSettings.forEach(settings => { this._overrides.get(settings.schemaId).forEach((value, key) => { if (value) settings.set_value(key, value); else settings.reset(key); }); }); } this._settings.reset('overridden-settings'); } destroy() { this._clear(); this._maybeNullValue = null; this._originalSettings = null; this._overrides = null; this._settings = null; } } export default class TilingAssistantExtension extends Extension { async enable() { this.settings = (await import('./src/common.js')).Settings; this.settings.initialize(this.getSettings()); this._settingsOverrider = new SettingsOverrider(this.settings); const twmModule = await import('./src/extension/tilingWindowManager.js'); this._twm = twmModule.TilingWindowManager; this._twm.initialize(); this._moveHandler = new MoveHandler(); this._resizeHandler = new ResizeHandler(); this._keybindingHandler = new KeybindingHandler(); this._layoutsManager = new LayoutsManager(); this._activeWindowHintHandler = new ActiveWindowHint(); this._altTabOverride = new AltTabOverride(); // Disable native tiling. this._settingsOverrider.add(new Gio.Settings({ schema_id: 'org.gnome.mutter' }), 'edge-tiling', new GLib.Variant('b', false)); // Disable native keybindings for Super+Up/Down/Left/Right const gnomeMutterKeybindings = new Gio.Settings({ schema_id: 'org.gnome.mutter.keybindings' }); const gnomeDesktopKeybindings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.keybindings' }); const sc = (await import('./src/common.js')).Shortcuts; const emptyStrvVariant = new GLib.Variant('as', []); if (gnomeDesktopKeybindings.get_strv('maximize').includes('Up') && this.settings.getStrv(sc.MAXIMIZE).includes('Up')) { this._settingsOverrider.add(gnomeDesktopKeybindings, 'maximize', emptyStrvVariant); } if (gnomeDesktopKeybindings.get_strv('unmaximize').includes('Down') && this.settings.getStrv(sc.RESTORE_WINDOW).includes('Down')) { this._settingsOverrider.add(gnomeDesktopKeybindings, 'unmaximize', emptyStrvVariant); } if (gnomeMutterKeybindings.get_strv('toggle-tiled-left').includes('Left') && this.settings.getStrv(sc.LEFT).includes('Left')) { this._settingsOverrider.add(gnomeMutterKeybindings, 'toggle-tiled-left', emptyStrvVariant); } if (gnomeMutterKeybindings.get_strv('toggle-tiled-right').includes('Right') && this.settings.getStrv(sc.RIGHT).includes('Right')) { this._settingsOverrider.add(gnomeMutterKeybindings, 'toggle-tiled-right', emptyStrvVariant); } // Include tiled windows when dragging from the top panel. this._getDraggableWindowForPosition = Main.panel._getDraggableWindowForPosition; Main.panel._getDraggableWindowForPosition = function (stageX) { const workspaceManager = global.workspace_manager; const windows = workspaceManager.get_active_workspace().list_windows(); const allWindowsByStacking = global.display.sort_windows_by_stacking(windows).reverse(); return allWindowsByStacking.find(w => { const rect = w.get_frame_rect(); const workArea = w.get_work_area_current_monitor(); return w.is_on_primary_monitor() && w.showing_on_its_workspace() && w.get_window_type() !== Meta.WindowType.DESKTOP && (w.maximized_vertically || w.tiledRect?.y === workArea.y) && stageX > rect.x && stageX < rect.x + rect.width; }); }; // Restore tiled window properties after session was unlocked. this._loadAfterSessionLock(); // Setting used for detection of a fresh install and do compatibility // changes if necessary... this.settings.setInt('last-version-installed', this.metadata.version); } disable() { // Save tiled window properties, if the session was locked to restore // them after the session is unlocked again. this._saveBeforeSessionLock(); this._settingsOverrider.destroy(); this._settingsOverrider = null; this._moveHandler.destroy(); this._moveHandler = null; this._resizeHandler.destroy(); this._resizeHandler = null; this._keybindingHandler.destroy(); this._keybindingHandler = null; this._layoutsManager.destroy(); this._layoutsManager = null; this._activeWindowHintHandler.destroy(); this._activeWindowHintHandler = null; this._altTabOverride.destroy(); this._altTabOverride = null; this._twm.destroy(); this._twm = null; this.settings.destroy(); this.settings = null; // Restore old functions. Main.panel._getDraggableWindowForPosition = this._getDraggableWindowForPosition; this._getDraggableWindowForPosition = null; // Delete custom tiling properties. const openWindows = global.display.get_tab_list(Meta.TabList.NORMAL, null); openWindows.forEach(w => { delete w.isTiled; delete w.tiledRect; delete w.untiledRect; }); } /** * Extensions are disabled when the screen is locked. So save the custom tiling * properties of windows before locking the screen. */ _saveBeforeSessionLock() { if (!Main.sessionMode.isLocked) return; this._wasLocked = true; const rectToJsObj = rect => rect && { x: rect.x, y: rect.y, width: rect.width, height: rect.height }; // can't just check for isTiled because maximized windows may // have an untiledRect as well in case window gaps are used const openWindows = this._twm.getWindows(true); const savedWindows = openWindows.filter(w => w.untiledRect).map(w => { return { windowId: w.get_stable_sequence(), isTiled: w.isTiled, tiledRect: rectToJsObj(w.tiledRect), untiledRect: rectToJsObj(w.untiledRect) }; }); const saveObj = { 'windows': savedWindows, 'tileGroups': Array.from(this._twm.getTileGroups()) }; const userPath = GLib.get_user_config_dir(); const parentPath = GLib.build_filenamev([userPath, '/tiling-assistant']); const parent = Gio.File.new_for_path(parentPath); try { parent.make_directory_with_parents(null); } catch (e) {} const path = GLib.build_filenamev([parentPath, '/tiledSessionRestore.json']); const file = Gio.File.new_for_path(path); try { file.create(Gio.FileCreateFlags.NONE, null); } catch (e) {} file.replace_contents(JSON.stringify(saveObj), null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, null); } /** * Extensions are disabled when the screen is locked. After having saved them, * reload them here. */ _loadAfterSessionLock() { if (!this._wasLocked) return; this._wasLocked = false; const userPath = GLib.get_user_config_dir(); const path = GLib.build_filenamev([userPath, '/tiling-assistant/tiledSessionRestore.json']); const file = Gio.File.new_for_path(path); if (!file.query_exists(null)) return; try { file.create(Gio.FileCreateFlags.NONE, null); } catch (e) {} const [success, contents] = file.load_contents(null); if (!success || !contents.length) return; const openWindows = this._twm.getWindows(true); const saveObj = JSON.parse(new TextDecoder().decode(contents)); const windowObjects = saveObj['windows']; windowObjects.forEach(wObj => { const { windowId, isTiled, tiledRect, untiledRect } = wObj; const window = openWindows.find(w => w.get_stable_sequence() === windowId); if (!window) return; const jsToRect = jsRect => jsRect && new Rect( jsRect.x, jsRect.y, jsRect.width, jsRect.height ); window.isTiled = isTiled; window.tiledRect = jsToRect(tiledRect); window.untiledRect = jsToRect(untiledRect); }); const tileGroups = new Map(saveObj['tileGroups']); this._twm.setTileGroups(tileGroups); openWindows.forEach(w => { if (tileGroups.has(w.get_id())) { const group = this._twm.getTileGroupFor(w); this._twm.updateTileGroup(group); } }); } } Tiling-Assistant-46/tiling-assistant@leleat-on-github/media/000077500000000000000000000000001457776040200242535ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/media/insert-link-symbolic.svg000066400000000000000000000036641457776040200310630ustar00rootroot00000000000000 Tiling-Assistant-46/tiling-assistant@leleat-on-github/media/preferences-desktop-apps-symbolic.svg000066400000000000000000000007351457776040200335310ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/metadata.json000066400000000000000000000006451457776040200256540ustar00rootroot00000000000000{ "description": "Expand GNOME's 2 column tiling and add a Windows-snap-assist-inspired popup...", "name": "Tiling Assistant", "shell-version": [ "45", "46" ], "url": "https://github.com/Leleat/Tiling-Assistant", "uuid": "tiling-assistant@leleat-on-github", "gettext-domain": "tiling-assistant@leleat-on-github", "settings-schema": "org.gnome.shell.extensions.tiling-assistant", "version": 46 } Tiling-Assistant-46/tiling-assistant@leleat-on-github/prefs.js000066400000000000000000000264101457776040200246540ustar00rootroot00000000000000import { Gdk, Gio, GLib, Gtk } from './src/dependencies/prefs/gi.js'; import { ExtensionPreferences } from './src/dependencies/prefs.js'; import LayoutPrefs from './src/prefs/layoutsPrefs.js'; import { Settings, Shortcuts } from './src/common.js'; // eslint-disable-next-line no-unused-vars import { ShortcutListener } from './src/prefs/shortcutListener.js'; export default class Prefs extends ExtensionPreferences { fillPreferencesWindow(window) { // Load css file const provider = new Gtk.CssProvider(); const path = GLib.build_filenamev([this.path, 'stylesheet.css']); provider.load_from_path(path); Gtk.StyleContext.add_provider_for_display( Gdk.Display.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ); window.set_can_navigate_back(true); const settings = this.getSettings(); const builder = new Gtk.Builder(); builder.set_translation_domain(this.uuid); builder.add_from_file(`${this.path}/src/ui/prefs.ui`); // Add general preference page window.add(builder.get_object('general')); // Add keybindings preference page window.add(builder.get_object('keybindings')); // Add layouts preference page on condition of advanced setting const layoutsPage = builder.get_object('layouts'); settings.connect(`changed::${Settings.ENABLE_ADV_EXP_SETTINGS}`, () => { settings.get_boolean(Settings.ENABLE_ADV_EXP_SETTINGS) ? window.add(layoutsPage) : window.remove(layoutsPage); }); if (settings.get_boolean(Settings.ENABLE_ADV_EXP_SETTINGS)) window.add(layoutsPage); // Bind settings to GUI this._bindSwitches(settings, builder); this._bindSpinbuttons(settings, builder); this._bindComboRows(settings, builder); this._bindRadioButtons(settings, builder); this._bindKeybindings(settings, builder); this._bindColorButtons(settings, builder); // LayoutPrefs manages everything related to layouts on the // prefs side (including the keyboard shortcuts) new LayoutPrefs(settings, builder, this.path); // Set visibility for deprecated settings this._setDeprecatedSettings(settings, builder); // Add a button into the headerbar with info this._addHeaderBarInfoButton(window, settings, builder); } /* * Bind GUI switches to settings. */ _bindSwitches(settings, builder) { const switches = [ Settings.ENABLE_TILING_POPUP, Settings.POPUP_ALL_WORKSPACES, Settings.RAISE_TILE_GROUPS, Settings.TILEGROUPS_IN_APP_SWITCHER, Settings.MAXIMIZE_WITH_GAPS, Settings.SHOW_LAYOUT_INDICATOR, Settings.ENABLE_ADV_EXP_SETTINGS, Settings.DISABLE_TILE_GROUPS, Settings.LOW_PERFORMANCE_MOVE_MODE, Settings.MONITOR_SWITCH_GRACE_PERIOD, Settings.ADAPT_EDGE_TILING_TO_FAVORITE_LAYOUT, Settings.ENABLE_TILE_ANIMATIONS, Settings.ENABLE_UNTILE_ANIMATIONS, Settings.ENABLE_HOLD_INVERSE_LANDSCAPE, Settings.ENABLE_HOLD_INVERSE_PORTRAIT ]; switches.forEach(key => { const widget = builder.get_object(key.replaceAll('-', '_')); settings.bind(key, widget, 'active', Gio.SettingsBindFlags.DEFAULT); }); } /* * Bind GUI spinbuttons to settings. */ _bindSpinbuttons(settings, builder) { const spinButtons = [ Settings.WINDOW_GAP, Settings.SINGLE_SCREEN_GAP, Settings.SCREEN_TOP_GAP, Settings.SCREEN_LEFT_GAP, Settings.SCREEN_RIGHT_GAP, Settings.SCREEN_BOTTOM_GAP, Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE, Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE, Settings.INVERSE_TOP_MAXIMIZE_TIMER, Settings.VERTICAL_PREVIEW_AREA, Settings.HORIZONTAL_PREVIEW_AREA ]; spinButtons.forEach(key => { const widget = builder.get_object(key.replaceAll('-', '_')); settings.bind(key, widget, 'value', Gio.SettingsBindFlags.DEFAULT); }); } /* * Bind GUI AdwComboRows to settings. */ _bindComboRows(settings, builder) { const comboRows = [ Settings.ADAPTIVE_TILING_MOD, Settings.FAVORITE_LAYOUT_MOD, Settings.IGNORE_TA_MOD, Settings.RESTORE_SIZE_ON ]; comboRows.forEach(key => { const widget = builder.get_object(key.replaceAll('-', '_')); settings.bind(key, widget, 'selected', Gio.SettingsBindFlags.DEFAULT); widget.set_selected(settings.get_int(key)); }); } /* * Bind GUI color buttons to settings. */ _bindColorButtons(settings, builder) { const switches = [ Settings.ACTIVE_WINDOW_HINT_COLOR ]; switches.forEach(key => { const widget = builder.get_object(`${key.replaceAll('-', '_')}_button`); widget.connect('color-set', () => { settings.set_string(key, widget.get_rgba().to_string()); }); // initilaize color const rgba = new Gdk.RGBA(); rgba.parse(settings.get_string(key)); widget.set_rgba(rgba); }); } /* * Bind radioButtons to settings. */ _bindRadioButtons(settings, builder) { // These 'radioButtons' are basically just used as a 'fake ComboBox' with // explanations for the different options. So there is just *one* gsetting // (an int) which saves the current 'selection'. const radioButtons = [ { key: Settings.DYNAMIC_KEYBINDINGS, rowNames: [ 'dynamic_keybinding_disabled_row', 'dynamic_keybinding_window_focus_row', 'dynamic_keybinding_tiling_state_row', 'dynamic_keybinding_tiling_state_windows_row', 'dynamic_keybinding_favorite_layout_row' ] }, { key: Settings.ACTIVE_WINDOW_HINT, rowNames: [ 'active_window_hint_disabled_row', 'active_window_hint_minimal_row', 'active_window_hint_always_row' ] }, { key: Settings.DEFAULT_MOVE_MODE, rowNames: [ 'edge_tiling_row', 'adaptive_tiling_row', 'favorite_layout_row', 'ignore_ta_row' ] } ]; radioButtons.forEach(({ key, rowNames }) => { const currActive = settings.get_int(key); rowNames.forEach((name, idx) => { const row = builder.get_object(name.replaceAll('-', '_')); const checkButton = row.activatable_widget; checkButton.connect('toggled', () => settings.set_int(key, idx)); // Set initial state if (idx === currActive) checkButton.activate(); }); }); } /* * Bind keybinding widgets to settings. */ _bindKeybindings(settings, builder) { const shortcuts = Shortcuts.getAllKeys(); shortcuts.forEach(key => { const shortcut = builder.get_object(key.replaceAll('-', '_')); shortcut.initialize(key, settings); }); } /** * Sets the visibility of deprecated settings. Those setting aren't visible * in the GUI unless they have a user set value. That means they aren't * discoverable through the GUI and need to first be set with the gsetting. * The normal rows should have the id of: GSETTING_WITH_UNDERSCORES_row. * ShortcutListeners have the format of GSETTING_WITH_UNDERSCORES. */ _setDeprecatedSettings(settings, builder) { // Keybindings ['toggle-tiling-popup', 'auto-tile'].forEach(s => { const isNonDefault = settings.get_strv(s)[0] !== settings.get_default_value(s).get_strv()[0]; builder.get_object(s.replaceAll('-', '_')).set_visible(isNonDefault); }); // Switches ['tilegroups-in-app-switcher'].forEach(s => { const isNonDefault = settings.get_boolean(s) !== settings.get_default_value(s).get_boolean(); builder.get_object(`${s.replaceAll('-', '_')}_row`).set_visible(isNonDefault); }); } _addHeaderBarInfoButton(window, settings, builder) { // Add headerBar button for menu // TODO: is this a 'reliable' method to access the headerbar? const page = builder.get_object('general'); const gtkStack = page .get_parent() .get_parent() .get_parent(); const adwHeaderBar = gtkStack .get_next_sibling() .get_first_child() .get_first_child() .get_first_child(); adwHeaderBar.pack_start(builder.get_object('info_menu')); // Setup menu actions const actionGroup = new Gio.SimpleActionGroup(); window.insert_action_group('prefs', actionGroup); const bugReportAction = new Gio.SimpleAction({ name: 'open-bug-report' }); bugReportAction.connect('activate', this._openBugReport.bind(this, window)); actionGroup.add_action(bugReportAction); const userGuideAction = new Gio.SimpleAction({ name: 'open-user-guide' }); userGuideAction.connect('activate', this._openUserGuide.bind(this, window)); actionGroup.add_action(userGuideAction); const changelogAction = new Gio.SimpleAction({ name: 'open-changelog' }); changelogAction.connect('activate', this._openChangelog.bind(this, window)); actionGroup.add_action(changelogAction); const licenseAction = new Gio.SimpleAction({ name: 'open-license' }); licenseAction.connect('activate', this._openLicense.bind(this, window)); actionGroup.add_action(licenseAction); const hiddenSettingsAction = new Gio.SimpleAction({ name: 'open-hidden-settings' }); hiddenSettingsAction.connect('activate', this._openHiddenSettings.bind(this, window, builder)); actionGroup.add_action(hiddenSettingsAction); // Button to return to main settings page const returnButton = builder.get_object('hidden_settings_return_button'); returnButton.connect('clicked', () => window.close_subpage()); } _openBugReport(window) { Gtk.show_uri(window, 'https://github.com/Leleat/Tiling-Assistant/issues', Gdk.CURRENT_TIME); } _openUserGuide(window) { Gtk.show_uri(window, 'https://github.com/Leleat/Tiling-Assistant/wiki', Gdk.CURRENT_TIME); } _openChangelog(window) { Gtk.show_uri(window, 'https://github.com/Leleat/Tiling-Assistant/blob/main/CHANGELOG.md', Gdk.CURRENT_TIME); } _openLicense(window) { Gtk.show_uri(window, 'https://github.com/Leleat/Tiling-Assistant/blob/main/LICENSE', Gdk.CURRENT_TIME); } _openHiddenSettings(window, builder) { const hiddenSettingsPage = builder.get_object('hidden_settings'); window.present_subpage(hiddenSettingsPage); } } Tiling-Assistant-46/tiling-assistant@leleat-on-github/schemas/000077500000000000000000000000001457776040200246175ustar00rootroot00000000000000org.gnome.shell.extensions.tiling-assistant.gschema.xml000066400000000000000000000201231457776040200373610ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/schemas true false true false 0 1 '' 5 0 0 0 0 0 0 0 false true [] [] [] [] Up','KP_5']]]> [] [] Down']]]> [] KP_8']]]> KP_2']]]> Left','KP_4']]]> Right','KP_6']]]> KP_7']]]> KP_9']]]> KP_1']]]> KP_3']]]> [] [] [] [] [] [] [] [] true false [] -1 [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] false true true false 0 false false 1 2 0 15 15 600 false false 0 [] [] -1 [] Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/000077500000000000000000000000001457776040200237635ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/common.js000066400000000000000000000303501457776040200256120ustar00rootroot00000000000000/** * Helper classes / enums for the settings.xml used in the extension files * *and* prefs files */ /** * A Singleton providing access to the settings. */ export class Settings { static _settings; static ENABLE_TILING_POPUP = 'enable-tiling-popup'; static POPUP_ALL_WORKSPACES = 'tiling-popup-all-workspace'; static RAISE_TILE_GROUPS = 'enable-raise-tile-group'; static TILEGROUPS_IN_APP_SWITCHER = 'tilegroups-in-app-switcher'; static WINDOW_GAP = 'window-gap'; static SINGLE_SCREEN_GAP = 'single-screen-gap'; static SCREEN_TOP_GAP = 'screen-top-gap'; static SCREEN_LEFT_GAP = 'screen-left-gap'; static SCREEN_RIGHT_GAP = 'screen-right-gap'; static SCREEN_BOTTOM_GAP = 'screen-bottom-gap'; static MAXIMIZE_WITH_GAPS = 'maximize-with-gap'; static DYNAMIC_KEYBINDINGS = 'dynamic-keybinding-behavior'; static ACTIVE_WINDOW_HINT = 'active-window-hint'; static ACTIVE_WINDOW_HINT_COLOR = 'active-window-hint-color'; static ACTIVE_WINDOW_HINT_BORDER_SIZE = 'active-window-hint-border-size'; static ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE = 'active-window-hint-inner-border-size'; static SHOW_LAYOUT_INDICATOR = 'show-layout-panel-indicator'; static ENABLE_ADV_EXP_SETTINGS = 'enable-advanced-experimental-features'; static DISABLE_TILE_GROUPS = 'disable-tile-groups'; static ENABLE_TILE_ANIMATIONS = 'enable-tile-animations'; static ENABLE_UNTILE_ANIMATIONS = 'enable-untile-animations'; static FAVORITE_LAYOUTS = 'favorite-layouts'; static DEFAULT_MOVE_MODE = 'default-move-mode'; static LOW_PERFORMANCE_MOVE_MODE = 'low-performance-move-mode'; static MONITOR_SWITCH_GRACE_PERIOD = 'monitor-switch-grace-period'; static ADAPT_EDGE_TILING_TO_FAVORITE_LAYOUT = 'adapt-edge-tiling-to-favorite-layout'; static ADAPTIVE_TILING_MOD = 'move-adaptive-tiling-mod'; static FAVORITE_LAYOUT_MOD = 'move-favorite-layout-mod'; static IGNORE_TA_MOD = 'ignore-ta-mod'; static VERTICAL_PREVIEW_AREA = 'vertical-preview-area'; static HORIZONTAL_PREVIEW_AREA = 'horizontal-preview-area'; static INVERSE_TOP_MAXIMIZE_TIMER = 'toggle-maximize-tophalf-timer'; static ENABLE_HOLD_INVERSE_LANDSCAPE = 'enable-hold-maximize-inverse-landscape'; static ENABLE_HOLD_INVERSE_PORTRAIT = 'enable-hold-maximize-inverse-portrait'; static RESTORE_SIZE_ON = 'restore-window-size-on'; static initialize(gioSettings) { this._settings = gioSettings; } static destroy() { this._settings = null; } /** * @returns {Gio.Settings} the Gio.Settings object. */ static getGioObject() { return this._settings; } /** * Listens for the change of a setting. * * @param {string} key a settings key. * @param {*} func function to call when the setting changed. */ static changed(key, func) { return this._settings.connect(`changed::${key}`, func); } static disconnect(id) { this._settings.disconnect(id); } /** * @returns {string[]} the settings keys except the ones for shortcuts. */ static getAllKeys() { return [ this.ENABLE_TILING_POPUP, this.POPUP_ALL_WORKSPACES, this.RAISE_TILE_GROUPS, this.TILEGROUPS_IN_APP_SWITCHER, this.WINDOW_GAP, this.SINGLE_SCREEN_GAP, this.SCREEN_TOP_GAP, this.SCREEN_LEFT_GAP, this.SCREEN_RIGHT_GAP, this.SCREEN_BOTTOM_GAP, this.MAXIMIZE_WITH_GAPS, this.DYNAMIC_KEYBINDINGS, this.ACTIVE_WINDOW_HINT, this.ACTIVE_WINDOW_HINT_COLOR, this.ACTIVE_WINDOW_HINT_BORDER_SIZE, this.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE, this.SHOW_LAYOUT_INDICATOR, this.ENABLE_ADV_EXP_SETTINGS, this.DISABLE_TILE_GROUPS, this.ENABLE_TILE_ANIMATIONS, this.ENABLE_UNTILE_ANIMATIONS, this.FAVORITE_LAYOUTS, this.DEFAULT_MOVE_MODE, this.LOW_PERFORMANCE_MOVE_MODE, this.MONITOR_SWITCH_GRACE_PERIOD, this.ADAPT_EDGE_TILING_TO_FAVORITE_LAYOUT, this.ADAPTIVE_TILING_MOD, this.FAVORITE_LAYOUT_MOD, this.IGNORE_TA_MOD, this.VERTICAL_PREVIEW_AREA, this.HORIZONTAL_PREVIEW_AREA, this.INVERSE_TOP_MAXIMIZE_TIMER, this.ENABLE_HOLD_INVERSE_LANDSCAPE, this.ENABLE_HOLD_INVERSE_PORTRAIT, this.RESTORE_SIZE_ON ]; } /** * Getters */ static getEnum(key) { return this._settings.get_enum(key); } static getString(key) { return this._settings.get_string(key); } static getStrv(key) { return this._settings.get_strv(key); } static getInt(key) { return this._settings.get_int(key); } static getBoolean(key) { return this._settings.get_boolean(key); } static getValue(key) { return this._settings.get_value(key); } static getUserValue(key) { return this._settings.get_user_value(key); } /** * Setters */ static setEnum(key, value) { this._settings.set_enum(key, value); } static setString(key, value) { this._settings.set_string(key, value); } static setStrv(key, value) { this._settings.set_strv(key, value); } static setInt(key, value) { this._settings.set_int(key, value); } static setBoolean(key, value) { this._settings.set_boolean(key, value); } static setValue(key, value) { return this._settings.set_value(key, value); } static reset(key) { this._settings.reset(key); } } /** * A Singleton providing access to the shortcut keys except the * ones related to the Layouts. */ export class Shortcuts { static TOGGLE_POPUP = 'toggle-tiling-popup'; static EDIT_MODE = 'tile-edit-mode'; static AUTO_FILL = 'auto-tile'; static ALWAYS_ON_TOP = 'toggle-always-on-top'; static MAXIMIZE = 'tile-maximize'; static MAXIMIZE_V = 'tile-maximize-vertically'; static MAXIMIZE_H = 'tile-maximize-horizontally'; static RESTORE_WINDOW = 'restore-window'; static CENTER_WINDOW = 'center-window'; static TOP = 'tile-top-half'; static BOTTOM = 'tile-bottom-half'; static LEFT = 'tile-left-half'; static RIGHT = 'tile-right-half'; static TOP_LEFT = 'tile-topleft-quarter'; static TOP_RIGHT = 'tile-topright-quarter'; static BOTTOM_LEFT = 'tile-bottomleft-quarter'; static BOTTOM_RIGHT = 'tile-bottomright-quarter'; static TOP_IGNORE_TA = 'tile-top-half-ignore-ta'; static BOTTOM_IGNORE_TA = 'tile-bottom-half-ignore-ta'; static LEFT_IGNORE_TA = 'tile-left-half-ignore-ta'; static RIGHT_IGNORE_TA = 'tile-right-half-ignore-ta'; static TOP_LEFT_IGNORE_TA = 'tile-topleft-quarter-ignore-ta'; static TOP_RIGHT_IGNORE_TA = 'tile-topright-quarter-ignore-ta'; static BOTTOM_LEFT_IGNORE_TA = 'tile-bottomleft-quarter-ignore-ta'; static BOTTOM_RIGHT_IGNORE_TA = 'tile-bottomright-quarter-ignore-ta'; static DEBUGGING = 'debugging-show-tiled-rects'; static DEBUGGING_FREE_RECTS = 'debugging-free-rects'; /** * @returns {string[]} the settings keys for the shortcuts in the same * order as they appear in the preference window. */ static getAllKeys() { return [ this.TOGGLE_POPUP, this.EDIT_MODE, this.AUTO_FILL, this.ALWAYS_ON_TOP, this.MAXIMIZE, this.MAXIMIZE_V, this.MAXIMIZE_H, this.RESTORE_WINDOW, this.CENTER_WINDOW, this.TOP, this.BOTTOM, this.LEFT, this.RIGHT, this.TOP_LEFT, this.TOP_RIGHT, this.BOTTOM_LEFT, this.BOTTOM_RIGHT, this.TOP_IGNORE_TA, this.BOTTOM_IGNORE_TA, this.LEFT_IGNORE_TA, this.RIGHT_IGNORE_TA, this.TOP_LEFT_IGNORE_TA, this.TOP_RIGHT_IGNORE_TA, this.BOTTOM_LEFT_IGNORE_TA, this.BOTTOM_RIGHT_IGNORE_TA, this.DEBUGGING, this.DEBUGGING_FREE_RECTS ]; } } // Enums: export class RestoreOn { static ON_GRAB_START = 0; // Grab Start static ON_GRAB_END = 1; // 'Grab End' } export class DynamicKeybindings { // Order comes from prefs static DISABLED = 0; static FOCUS = 1; static TILING_STATE = 2; static TILING_STATE_WINDOWS = 3; static FAVORITE_LAYOUT = 4; } export class MoveModes { // Order comes from prefs static EDGE_TILING = 0; static ADAPTIVE_TILING = 1; static FAVORITE_LAYOUT = 2; static IGNORE_TA = 3; } export class Orientation { static H = 1; static V = 2; } export class Direction { static N = 1; static E = 2; static S = 4; static W = 8; static opposite(dir) { let opposite = 0; if (dir & this.N) opposite |= this.S; if (dir & this.S) opposite |= this.N; if (dir & this.W) opposite |= this.E; if (dir & this.E) opposite |= this.W; return opposite; } } // Classes for the layouts: // See src/prefs/layoutsPrefs.js for details on layouts. export class Layout { /** * @param {object} layout is the parsed object from the layouts file. */ constructor(layout = null) { this._name = layout?._name ?? ''; this._items = layout?._items ?? []; } /** * @returns {string} */ getName() { return this._name; } /** * @param {string} name */ setName(name) { this._name = name; } /** * @param {number} index * @returns {LayoutItem} */ getItem(index) { return this._items[index]; } /** * @param {LayoutItem|null} item * @returns {LayoutItem} the added item. */ addItem(item = null) { item = item ?? new LayoutItem(); this._items.push(item); return item; } /** * @param {number} index * @returns {LayoutItem|null} the removed item. */ removeItem(index) { return this._items.splice(index, 1)[0]; } /** * @param {boolean} filterOutEmptyRects * @returns {LayoutItem[]} */ getItems(filterOutEmptyRects = true) { return filterOutEmptyRects ? this._items.filter(i => Object.keys(i.rect).length === 4) : this._items; } /** * @param {LayoutItem[]} items */ setItems(items) { this._items = items; } /** * @param {boolean} filterOutEmptyRects * @returns {number} */ getItemCount(filterOutEmptyRects = false) { return filterOutEmptyRects ? this.getItems().length : this._items.length; } /** * @returns {[boolean, string]} whether the layout has valid rects and * a potential error message. */ validate() { const rects = this.getItems().map(i => i.rect); if (!rects.length) return [false, 'No valid rectangles defined.', -1]; const getOverlapArea = (r1, r2) => { return Math.max(0, Math.min(r1.x + r1.width, r2.x + r2.width) - Math.max(r1.x, r2.x)) * Math.max(0, Math.min(r1.y + r1.height, r2.y + r2.height) - Math.max(r1.y, r2.y)); }; for (let i = 0; i < rects.length; i++) { const rect = rects[i]; if (rect.width <= 0 || rect.width > 1) return [false, `Rectangle ${i} has an invalid width.`, i]; if (rect.height <= 0 || rect.height > 1) return [false, `Rectangle ${i} has an invalid height.`, i]; if (rect.x < 0 || rect.y < 0 || rect.x + rect.width > 1 || rect.y + rect.height > 1) return [false, `Rectangle ${i} extends beyond the screen.`, i]; for (let j = i + 1; j < rects.length; j++) { if (getOverlapArea(rect, rects[j]) !== 0) return [false, `Rectangles ${i} and ${j} overlap.`, j]; } } return [true, '', -1]; } } var LayoutItem = class LayoutItem { constructor() { this.rect = {}; this.appId = null; this.loopType = null; } }; Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/000077500000000000000000000000001457776040200264115ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/gi.js000066400000000000000000000006311457776040200273460ustar00rootroot00000000000000export { default as Atk } from 'gi://Atk'; export { default as Clutter } from 'gi://Clutter'; export { default as Gio } from 'gi://Gio'; export { default as GLib } from 'gi://GLib'; export { default as GObject } from 'gi://GObject'; export { default as Meta } from 'gi://Meta'; export { default as Mtk } from 'gi://Mtk'; export { default as Shell } from 'gi://Shell'; export { default as St } from 'gi://St'; Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/prefs.js000066400000000000000000000001741457776040200300700ustar00rootroot00000000000000export { ExtensionPreferences, gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/prefs/000077500000000000000000000000001457776040200275305ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/prefs/gi.js000066400000000000000000000004141457776040200304640ustar00rootroot00000000000000export { default as Adw } from 'gi://Adw'; export { default as Gdk } from 'gi://Gdk'; export { default as Gio } from 'gi://Gio'; export { default as GLib } from 'gi://GLib'; export { default as GObject } from 'gi://GObject'; export { default as Gtk } from 'gi://Gtk'; Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/shell.js000066400000000000000000000010441457776040200300550ustar00rootroot00000000000000export { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; export * as AltTab from 'resource:///org/gnome/shell/ui/altTab.js'; export * as Main from 'resource:///org/gnome/shell/ui/main.js'; export * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; export * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; export * as SwitcherPopup from 'resource:///org/gnome/shell/ui/switcherPopup.js'; export * as WindowManager from 'resource:///org/gnome/shell/ui/windowManager.js'; Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/unexported/000077500000000000000000000000001457776040200306065ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/unexported/altTab.js000066400000000000000000000014051457776040200323530ustar00rootroot00000000000000import { Meta } from '../gi.js'; export const baseIconSizes = [96, 64, 48, 32, 22]; export const APP_ICON_HOVER_TIMEOUT = 200; // milliseconds export function getWindows(workspace) { // We ignore skip-taskbar windows in switchers, but if they are attached // to their parent, their position in the MRU list may be more appropriate // than the parent; so start with the complete list ... let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, workspace); // ... map windows to their parent where appropriate ... return windows.map(w => { return w.is_attached_dialog() ? w.get_transient_for() : w; // ... and filter out skip-taskbar windows and duplicates }).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) === i); } Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/dependencies/unexported/windowManager.js000066400000000000000000000000521457776040200337430ustar00rootroot00000000000000export const WINDOW_ANIMATION_TIME = 250; Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/000077500000000000000000000000001457776040200257775ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/activeWindowHint.js000066400000000000000000000244411457776040200316300ustar00rootroot00000000000000import { Clutter, GObject, Meta, St } from '../dependencies/gi.js'; import { Main } from '../dependencies/shell.js'; import { Settings } from '../common.js'; import { TilingWindowManager as Twm } from './tilingWindowManager.js'; export default class ActiveWindowHintHandler { constructor() { // On a fresh install no color is set for the hint yet. Use the bg color // from the tile preview style by using a temporary widget. if (Settings.getString(Settings.ACTIVE_WINDOW_HINT_COLOR) === '') { const widget = new St.Widget({ style_class: 'tile-preview' }); global.stage.add_child(widget); const color = widget.get_theme_node().get_background_color(); const { red, green, blue } = color; Settings.setString(Settings.ACTIVE_WINDOW_HINT_COLOR, `rgb(${red},${green},${blue})`); widget.destroy(); } this._hint = null; this._settingsId = 0; this._setupHint(); this._settingsId = Settings.changed(Settings.ACTIVE_WINDOW_HINT, () => this._setupHint()); } destroy() { Settings.disconnect(this._settingsId); this._hint?.destroy(); this._hint = null; } _setupHint() { switch (Settings.getInt(Settings.ACTIVE_WINDOW_HINT)) { case 0: // Disabled this._hint?.destroy(); this._hint = null; break; case 1: // Minimal this._hint?.destroy(); this._hint = new MinimalHint(); break; case 2: // Always this._hint?.destroy(); this._hint = new AlwaysHint(); } } } const Hint = GObject.registerClass( class ActiveWindowHint extends St.Widget { _init() { super._init(); this._color = Settings.getString(Settings.ACTIVE_WINDOW_HINT_COLOR); this._borderSize = Settings.getInt(Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE); this._innerBorderSize = Settings.getInt(Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE); // 'Inner border' to cover rounded corners this._settingsIds = []; this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_COLOR, () => { this._color = Settings.getString(Settings.ACTIVE_WINDOW_HINT_COLOR); })); this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE, () => { this._borderSize = Settings.getInt(Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE); })); this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE, () => { this._innerBorderSize = Settings.getInt(Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE); })); global.window_group.add_child(this); } destroy() { this._settingsIds.forEach(id => Settings.disconnect(id)); super.destroy(); } }); const MinimalHint = GObject.registerClass( class MinimalActiveWindowHint extends Hint { _init() { super._init(); this._windowClone = null; this._updateStyle(); this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_COLOR, () => { this._updateStyle(); })); global.workspace_manager.connectObject('workspace-switched', () => this._onWsSwitched(), this); } destroy() { this._reset(); super.destroy(); } _reset() { if (this._laterId) { global.compositor.get_laters().remove(this._laterId); delete this._laterId; } this._windowClone?.destroy(); this._windowClone = null; this.hide(); } _updateStyle() { this.set_style(`background-color: ${this._color};`); } _onWsSwitched() { // Reset in case multiple workspaces are switched at once. this._reset(); // If we are in the overview, it's likely the user actively chose // a window to focus. So the hint is unnecessary. if (Main.overview.visible) return; const window = global.display.focus_window; if (!window) return; // Maximized or fullscreen windows don't require a hint since they // cover the entire screen. if (window.is_fullscreen() || Twm.isMaximized(window)) return; // Now figure out if the focused window is easily identifiable by // checking (in stacking order) if all other windows are being // overlapped by higher windows. If a window is not overlapped, the // focused window is ambiguous. const windows = Twm.getWindows(); const overlapping = windows.splice(windows.indexOf(window), 1); const notOverlappedWindowExists = windows.some(w => { if (!overlapping.some(o => o.get_frame_rect().overlap(w.get_frame_rect()))) return true; overlapping.push(w); return false; }); if (notOverlappedWindowExists) this._giveHint(window); } _giveHint(window) { this._scaleClone(window); this._rippleFade(window); } _scaleClone(window) { const actor = window.get_compositor_private(); if (!actor) return; const { x, y, width, height } = actor; const scaleAmount = 15; this._windowClone = new Clutter.Clone({ source: actor, x: x - scaleAmount, y: y - scaleAmount, width: width + 2 * scaleAmount, height: height + 2 * scaleAmount }); global.window_group.insert_child_above(this._windowClone, actor); this._windowClone.ease({ x, y, width, height, delay: 250, duration: 250, mode: Clutter.AnimationMode.EASE_OUT_QUAD, onComplete: () => { // May already have been destroyed by a reset this._windowClone?.destroy(); this._windowClone = null; } }); } _rippleFade(window) { const actor = window.get_compositor_private(); if (!actor) return; if (!this._laterId) { this._laterId = global.compositor.get_laters().add( Meta.LaterType.BEFORE_REDRAW, () => { global.window_group.set_child_below_sibling(this, actor); delete this._laterId; return false; } ); } const { x, y, width, height } = window.get_frame_rect(); this.set({ x, y, width, height }); this.set_opacity(255); this.show(); const rippleSize = 30; this.ease({ x: x - rippleSize, y: y - rippleSize, width: width + 2 * rippleSize, height: height + 2 * rippleSize, opacity: 0, delay: 250, duration: 350, mode: Clutter.AnimationMode.EASE_OUT_QUAD, onComplete: () => this.hide() }); } }); // TODO a solid bg color looks better than a border when launching an app since // the border will appear before the window is fully visible. However there was // an issue with global.window_group.set_child_below_sibling not putting the hint // below the window for some reason. laters-add solved it but I don't know // why. So as to not potentially cover the entire window's content use the border // style until I figure out if laters-add is the proper solution... const AlwaysHint = GObject.registerClass( class AlwaysActiveWindowHint extends Hint { _init() { super._init(); this._window = null; this._signalIds = []; this._updateGeometry(); this._updateStyle(); global.display.connectObject('notify::focus-window', () => this._updateGeometry(), this); this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_COLOR, () => { this._updateStyle(); this._updateGeometry(); })); this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_BORDER_SIZE, () => { this._updateStyle(); this._updateGeometry(); })); this._settingsIds.push(Settings.changed(Settings.ACTIVE_WINDOW_HINT_INNER_BORDER_SIZE, () => { this._updateStyle(); this._updateGeometry(); })); } destroy() { this._reset(); super.destroy(); } vfunc_hide() { this._cancelShowLater(); super.vfunc_hide(); } _reset() { this._cancelShowLater(); this._signalIds.forEach(id => this._window.disconnect(id)); this._signalIds = []; this._window = null; } _cancelShowLater() { if (!this._showLater) return; global.compositor.get_laters().remove(this._showLater); delete this._showLater; } _updateGeometry() { this._reset(); const window = global.display.focus_window; const allowTypes = [Meta.WindowType.NORMAL, Meta.WindowType.DIALOG, Meta.WindowType.MODAL_DIALOG]; if (!window || !allowTypes.includes(window.get_window_type())) { this.hide(); return; } this._window = window; this._signalIds.push(window.connect('position-changed', () => this._updateGeometry())); this._signalIds.push(window.connect('size-changed', () => this._updateGeometry())); // Don't show hint on maximzed/fullscreen windows if (window.is_fullscreen() || Twm.isMaximized(window)) { this.hide(); return; } const { x, y, width, height } = window.get_frame_rect(); this.set({ x, y, width, height }); const actor = window.get_compositor_private(); if (!actor || this._showLater) return; this._showLater = global.compositor.get_laters().add( Meta.LaterType.IDLE, () => { global.window_group.set_child_below_sibling(this, actor); this.show(); delete this._showLater; return false; } ); } _updateStyle() { this.set_style(` border: ${this._innerBorderSize}px solid ${this._color}; outline: ${this._borderSize}px solid ${this._color}; `); } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/altTab.js000066400000000000000000000415331457776040200275520ustar00rootroot00000000000000import { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } from '../dependencies/gi.js'; import { AltTab, Extension, Main, SwitcherPopup } from '../dependencies/shell.js'; import { baseIconSizes, APP_ICON_HOVER_TIMEOUT } from '../dependencies/unexported/altTab.js'; import { Settings } from '../common.js'; import { TilingWindowManager as Twm } from './tilingWindowManager.js'; /** * Optionally, override GNOME's altTab / appSwitcher to group tileGroups */ export default class AltTabOverride { constructor() { if (Settings.getBoolean(Settings.TILEGROUPS_IN_APP_SWITCHER)) this._overrideNativeAppSwitcher(); this._settingsId = Settings.changed(Settings.TILEGROUPS_IN_APP_SWITCHER, () => { if (Settings.getBoolean(Settings.TILEGROUPS_IN_APP_SWITCHER)) this._overrideNativeAppSwitcher(); else this._restoreNativeAppSwitcher(); }); } destroy() { Settings.disconnect(this._settingsId); this._restoreNativeAppSwitcher(); } _overrideNativeAppSwitcher() { Main.wm.setCustomKeybindingHandler( 'switch-applications', Shell.ActionMode.NORMAL, this._startSwitcher.bind(this) ); } _restoreNativeAppSwitcher() { Main.wm.setCustomKeybindingHandler( 'switch-applications', Shell.ActionMode.NORMAL, Main.wm._startSwitcher.bind(Main.wm) ); } /** * Copy-pasta from windowManager.js. Removed unused stuff... * * @param {*} display - * @param {*} window - * @param {*} binding - */ _startSwitcher(display, window, binding) { if (Main.wm._workspaceSwitcherPopup !== null) Main.wm._workspaceSwitcherPopup.destroy(); const tabPopup = new TilingAppSwitcherPopup(); if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) tabPopup.destroy(); } } export const TilingAppSwitcherPopup = GObject.registerClass( class TilingAppSwitcherPopup extends AltTab.AppSwitcherPopup { _init() { SwitcherPopup.SwitcherPopup.prototype._init.call(this); const settings = new Gio.Settings({ schema_id: 'org.gnome.shell.app-switcher' }); const workspace = settings.get_boolean('current-workspace-only') ? global.workspace_manager.get_active_workspace() : null; const windows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace); this._switcherList = new TilingAppSwitcher(this, windows); this._items = this._switcherList.icons; } // Called when closing an entire app / tileGroup _quitApplication(index) { const item = this._items[index]; if (!item) return; item.cachedWindows.forEach(w => w.delete(global.get_current_time())); item.cachedWindows = []; this._switcherList._removeIcon(item); } // Called when closing a window with the thumbnail switcher // meaning that .cachedWindow of an item was updated via signals _windowRemoved(thumbnailSwitcher, n) { const item = this._items[this._selectedIndex]; if (!item) return; if (item.cachedWindows.length) { const newIndex = Math.min(n, item.cachedWindows.length - 1); this._select(this._selectedIndex, newIndex); } item.updateAppIcons(); } }); export const TilingAppSwitcher = GObject.registerClass( class TilingAppSwitcher extends SwitcherPopup.SwitcherList { _init(altTabPopup, windows) { // Don't make the SwitcherButtons squares since 1 SwitcherButton // may contain multiple AppIcons for a tileGroup. super._init(false); this.icons = []; this._arrows = []; this._apps = []; this._altTabPopup = altTabPopup; this._delayedHighlighted = -1; this._mouseTimeOutId = 0; const winTracker = Shell.WindowTracker.get_default(); let groupedWindows; // Group windows based on their tileGroup, if tileGroup.length > 1. // Otherwise group them based on their respective apps. if (Settings.getBoolean(Settings.TILEGROUPS_IN_APP_SWITCHER)) { groupedWindows = windows.reduce((allGroups, w) => { for (const group of allGroups) { if (w.isTiled && Twm.getTileGroupFor(w).length > 1) { if (Twm.getTileGroupFor(w).includes(group[0])) { group.push(w); return allGroups; } } else if ((!group[0].isTiled || group[0].isTiled && Twm.getTileGroupFor(group[0]).length <= 1) && winTracker.get_window_app(group[0]) === winTracker.get_window_app(w)) { group.push(w); return allGroups; } } const newGroup = [w]; allGroups.push(newGroup); return allGroups; }, []); // Group windows based on apps } else { groupedWindows = windows.reduce((allGroups, w) => { for (const group of allGroups) { if (winTracker.get_window_app(group[0]) === winTracker.get_window_app(w)) { group.push(w); return allGroups; } } const newGroup = [w]; allGroups.push(newGroup); return allGroups; }, []); } // Construct the AppIcons and add them to the popup. groupedWindows.forEach(group => { const item = new AppSwitcherItem(group); item.connect('all-icons-removed', () => this._removeIcon(item)); this._addIcon(item); }); // Listen for the app stop state in case the app got closed outside // of the app switcher along with closing via the app switcher const allApps = windows.map(w => winTracker.get_window_app(w)); this._apps = [...new Set(allApps)]; this._stateChangedIds = this._apps.map(app => app.connect('notify::state', () => { if (app.state !== Shell.AppState.RUNNING) this.icons.forEach(item => item.removeApp(app)); })); this.connect('destroy', this._onDestroy.bind(this)); } _onDestroy() { if (this._mouseTimeOutId !== 0) GLib.source_remove(this._mouseTimeOutId); this._stateChangedIds?.forEach((id, index) => this._apps[index].disconnect(id)); this._stateChangedIds = []; this._apps = []; } _setIconSize() { let j = 0; while (this._items.length > 1 && this._items[j].style_class !== 'item-box') j++; let themeNode = this._items[j].get_theme_node(); this._list.ensure_style(); let iconPadding = themeNode.get_horizontal_padding(); let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT); let [, labelNaturalHeight] = this.icons[j].label.get_preferred_height(-1); let iconSpacing = labelNaturalHeight + iconPadding + iconBorder; let totalSpacing = this._list.spacing * (this._items.length - 1); // We just assume the whole screen here due to weirdness happening with the passed width let primary = Main.layoutManager.primaryMonitor; let parentPadding = this.get_parent().get_theme_node().get_horizontal_padding(); let availWidth = primary.width - parentPadding - this.get_theme_node().get_horizontal_padding(); let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let iconSizes = baseIconSizes.map(s => s * scaleFactor); let iconSize = baseIconSizes[0]; if (this._items.length > 1) { for (let i = 0; i < baseIconSizes.length; i++) { iconSize = baseIconSizes[i]; let height = iconSizes[i] + iconSpacing; let w = height * this._items.length + totalSpacing; if (w <= availWidth) break; } } this._iconSize = iconSize; for (let i = 0; i < this.icons.length; i++) { // eslint-disable-next-line eqeqeq if (this.icons[i].icon != null) break; this.icons[i].set_size(iconSize); } } vfunc_get_preferred_height(forWidth) { if (!this._iconSize) this._setIconSize(); return super.vfunc_get_preferred_height(forWidth); } vfunc_allocate(box) { // Allocate the main list items super.vfunc_allocate(box); let contentBox = this.get_theme_node().get_content_box(box); let arrowHeight = Math.floor(this.get_theme_node().get_padding(St.Side.BOTTOM) / 3); let arrowWidth = arrowHeight * 2; // Now allocate each arrow underneath its item let childBox = new Clutter.ActorBox(); for (let i = 0; i < this._items.length; i++) { let itemBox = this._items[i].allocation; childBox.x1 = contentBox.x1 + Math.floor(itemBox.x1 + (itemBox.x2 - itemBox.x1 - arrowWidth) / 2); childBox.x2 = childBox.x1 + arrowWidth; childBox.y1 = contentBox.y1 + itemBox.y2 + arrowHeight; childBox.y2 = childBox.y1 + arrowHeight; this._arrows[i].allocate(childBox); } } // We override SwitcherList's _onItemMotion method to delay // activation when the thumbnail list is open _onItemMotion(item) { if (item === this._items[this._highlighted] || item === this._items[this._delayedHighlighted]) return Clutter.EVENT_PROPAGATE; const index = this._items.indexOf(item); if (this._mouseTimeOutId !== 0) { GLib.source_remove(this._mouseTimeOutId); this._delayedHighlighted = -1; this._mouseTimeOutId = 0; } if (this._altTabPopup.thumbnailsVisible) { this._delayedHighlighted = index; this._mouseTimeOutId = GLib.timeout_add( GLib.PRIORITY_DEFAULT, APP_ICON_HOVER_TIMEOUT, () => { this._enterItem(index); this._delayedHighlighted = -1; this._mouseTimeOutId = 0; return GLib.SOURCE_REMOVE; }); GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem'); } else { this._itemEntered(index); } return Clutter.EVENT_PROPAGATE; } _enterItem(index) { let [x, y] = global.get_pointer(); let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); if (this._items[index].contains(pickedActor)) this._itemEntered(index); } // We override SwitcherList's highlight() method to also deal with // the AppSwitcher->ThumbnailSwitcher arrows. Apps with only 1 window // will hide their arrows by default, but show them when their // thumbnails are visible (ie, when the app icon is supposed to be // in justOutline mode). Apps with multiple windows will normally // show a dim arrow, but show a bright arrow when they are // highlighted. highlight(n, justOutline) { if (this.icons[this._highlighted]) { if (this.icons[this._highlighted].cachedWindows.length === 1) this._arrows[this._highlighted].hide(); else this._arrows[this._highlighted].remove_style_pseudo_class('highlighted'); } super.highlight(n, justOutline); if (this._highlighted !== -1) { if (justOutline && this.icons[this._highlighted].cachedWindows.length === 1) this._arrows[this._highlighted].show(); else this._arrows[this._highlighted].add_style_pseudo_class('highlighted'); } } _addIcon(appIcon) { this.icons.push(appIcon); let item = this.addItem(appIcon, appIcon.label); appIcon.app.connectObject('notify::state', app => { if (app.state !== Shell.AppState.RUNNING) this._removeIcon(app); }, this); let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' }); arrow.connect('repaint', () => SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM)); this.add_child(arrow); this._arrows.push(arrow); if (appIcon.cachedWindows.length === 1) arrow.hide(); else item.add_accessible_state(Atk.StateType.EXPANDABLE); } _removeIcon(item) { const index = this.icons.findIndex(i => i === item); if (index === -1) return; this._arrows[index].destroy(); this._arrows.splice(index, 1); this.icons.splice(index, 1); this.removeItem(index); } }); /** * Replace AltTab.AppIcon and insert this into the TilingAppSwitcher instead. * This may contain multiple AppIcons to represent a tileGroup with chain icons * between the AppIcons. */ const AppSwitcherItem = GObject.registerClass({ Signals: { 'all-icons-removed': {} } }, class AppSwitcherItem extends St.BoxLayout { _init(windows) { super._init({ vertical: false }); // A tiled window in a tileGroup of length 1, doesn't get a separate // AppSwitcherItem. It gets added to the non-tiled windows' AppSwitcherItem const tileGroup = windows[0].isTiled && Twm.getTileGroupFor(windows[0]); this.isTileGroup = tileGroup && tileGroup.every(w => windows.includes(w)) && tileGroup?.length > 1; this.cachedWindows = windows; this.appIcons = []; this.chainIcons = []; // Compatibility with AltTab.AppIcon this.set_size = size => this.appIcons.forEach(i => i.set_size(size)); this.label = null; this.app = { // Only raise the first window since we split up apps and tileGroups activate_window: (window, timestamp) => { Main.activateWindow(this.cachedWindows[0], timestamp); }, // Listening to the app-stop now happens in the custom _init func // So prevent signal connection. here.. careful in case signal // connection in the future is used for more... connectObject: () => {} }; this.updateAppIcons(); } // Re/Create the AppIcons based on the cached window list updateAppIcons() { this.appIcons.forEach(i => i.destroy()); this.appIcons = []; this.chainIcons.forEach(i => i.destroy()); this.chainIcons = []; const winTracker = Shell.WindowTracker.get_default(); const path = Extension.lookupByURL(import.meta.url) .dir.get_child('media/insert-link-symbolic.svg') .get_path(); const icon = new Gio.FileIcon({ file: Gio.File.new_for_path(path) }); const apps = this.isTileGroup // All apps (even duplicates) ? this.cachedWindows.map(w => winTracker.get_window_app(w)) // Only unique apps : this.cachedWindows.reduce((allApps, w) => { const a = winTracker.get_window_app(w); !allApps.includes(a) && allApps.push(a); return allApps; }, []); apps.forEach((app, idx) => { // AppIcon const appIcon = new AppIcon(app); this.add_child(appIcon); this.appIcons.push(appIcon); // Add chain to the right AppIcon except for the last AppIcon if (idx >= apps.length - 1) return; // Chain const chain = new St.Icon({ gicon: icon, icon_size: 18 }); this.add_child(chain); this.chainIcons.push(chain); }); if (!this.appIcons.length) { this.emit('all-icons-removed'); return; } this.label = this.appIcons[0].label; } // Remove an AppIcon to the corresponding app. // This doesn't update cached window list! removeApp(app) { for (let i = this.appIcons.length - 1; i >= 0; i--) { const appIcon = this.appIcons[i]; if (appIcon.app !== app) continue; this.appIcons.splice(i, 1); appIcon.destroy(); const chain = this.chainIcons.splice(Math.max(0, i - 1), 1)[0]; chain?.destroy(); } if (!this.appIcons.length) this.emit('all-icons-removed'); } }); const AppIcon = GObject.registerClass( class AppIcon extends AltTab.AppIcon { // Don't make the SwitcherButtons squares since 1 SwitcherButton // may contain multiple AppIcons for a tileGroup. vfunc_get_preferred_width() { return this.get_preferred_height(-1); } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js000066400000000000000000000540401457776040200317610ustar00rootroot00000000000000import { Clutter, Meta, Shell, St } from '../dependencies/gi.js'; import { _, Main } from '../dependencies/shell.js'; import { Direction, DynamicKeybindings, Settings, Shortcuts } from '../common.js'; import { Rect, Util } from './utility.js'; import { TilingWindowManager as Twm } from './tilingWindowManager.js'; /** * Class to handle the keyboard shortcuts (on the extension side) except the * ones related to the Layouts. For those, see layoutsManager.js. */ export default class TilingKeybindingHandler { constructor() { const allowInOverview = [Shortcuts.TOGGLE_POPUP]; this._keyBindings = Shortcuts.getAllKeys(); this._keyBindings.forEach(key => { Main.wm.addKeybinding( key, Settings.getGioObject(), Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, Shell.ActionMode.NORMAL | (allowInOverview.includes(key) && Shell.ActionMode.OVERVIEW), this._onCustomKeybindingPressed.bind(this, key) ); }); } destroy() { this._keyBindings.forEach(key => Main.wm.removeKeybinding(key)); this._debuggingIndicators?.forEach(i => i.destroy()); } /** * @param {string} shortcutName */ async _onCustomKeybindingPressed(shortcutName) { // Debugging const debugging = [Shortcuts.DEBUGGING, Shortcuts.DEBUGGING_FREE_RECTS]; if (debugging.includes(shortcutName)) { if (this._debuggingIndicators) { this._debuggingIndicators.forEach(i => i.destroy()); this._debuggingIndicators = null; } else { const createIndicators = shortcutName === Shortcuts.DEBUGGING ? Util.___debugShowTiledRects : Util.___debugShowFreeScreenRects; this._debuggingIndicators = await createIndicators.call(Util); } return; // Toggle the Tiling Popup } else if (shortcutName === Shortcuts.TOGGLE_POPUP) { const toggleTo = !Settings.getBoolean(Settings.ENABLE_TILING_POPUP); Settings.setBoolean(Settings.ENABLE_TILING_POPUP, toggleTo); Main.notify('Tiling Assistant', toggleTo ? _('Tiling popup enabled') : _('Tiling popup was disabled')); return; } const window = global.display.focus_window; if (!window) return; // Auto-tile: tile to empty space. If there's none: untile, // if it's already tiled else maximize if (shortcutName === Shortcuts.AUTO_FILL) { if (Twm.isMaximized(window)) { Twm.untile(window); } else { const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: !window.isTiled }); const tRects = topTileGroup.map(w => w.tiledRect); const tileRect = Twm.getBestFreeRect(tRects, { currRect: window.tiledRect }); Twm.toggleTiling(window, tileRect); } // Tile Editing Mode } else if (shortcutName === Shortcuts.EDIT_MODE) { const TileEditingMode = await import('./tileEditingMode.js'); const tileEditor = new TileEditingMode.TileEditor(); tileEditor.open(); // Toggle always-on-top } else if (shortcutName === Shortcuts.ALWAYS_ON_TOP) { window.is_above() ? window.unmake_above() : window.make_above(); // Toggle maximization vertically } else if (shortcutName === Shortcuts.MAXIMIZE_V) { const workArea = new Rect(window.get_work_area_current_monitor()); const currRect = window.tiledRect ?? window.get_frame_rect(); // Is tiled or maximized with this extension if (window.untiledRect && currRect.height === workArea.height) { // Is maximized if (currRect.width === workArea.width) { const tileRect = new Rect(workArea.x, window.untiledRect.y, workArea.width, window.untiledRect.height); Twm.tile(window, tileRect); // Is tiled } else { Twm.untile(window); } // Maximize vertically even if the height may already be equal to the workArea // e. g. via double-click titlebar, maximize-window-button or whatever } else { const tileRect = new Rect(currRect.x, workArea.y, currRect.width, workArea.height); Twm.tile(window, tileRect); } // Toggle maximization horizontally } else if (shortcutName === Shortcuts.MAXIMIZE_H) { const workArea = new Rect(window.get_work_area_current_monitor()); const currRect = window.tiledRect ?? window.get_frame_rect(); // Is tiled or maximized with this extension if (window.untiledRect && currRect.width === workArea.width) { // Is maximized if (currRect.height === workArea.height) { const tileRect = new Rect(window.untiledRect.x, workArea.y, window.untiledRect.width, workArea.height); Twm.tile(window, tileRect); // Is tiled } else { Twm.untile(window); } // Maximize horizontally even if the width may already be equal to the workArea // e. g. via double-click titlebar, maximize-window-button or whatever } else { const tileRect = new Rect(workArea.x, currRect.y, workArea.width, currRect.height); Twm.tile(window, tileRect); } // Restore window size } else if (shortcutName === Shortcuts.RESTORE_WINDOW) { if (window.untiledRect) // Tiled & maximized with gaps Twm.untile(window, { clampToWorkspace: true }); else if (window.get_maximized()) window.unmaximize(window.get_maximized()); // Center window } else if (shortcutName === Shortcuts.CENTER_WINDOW) { const workArea = new Rect(window.get_work_area_current_monitor()); if (window.isTiled) { const currRect = window.tiledRect; const tileRect = new Rect( workArea.center.x - Math.floor(currRect.width / 2), workArea.center.y - Math.floor(currRect.height / 2), currRect.width, currRect.height ); if (tileRect.equal(currRect)) return; Twm.tile(window, tileRect, { openTilingPopup: false }); } else if (!Twm.isMaximized(window)) { if (!window.allows_move()) return; const currRect = window.get_frame_rect(); const x = workArea.center.x - Math.floor(currRect.width / 2); const y = workArea.center.y - Math.floor(currRect.height / 2); if (x === currRect.x && y === currRect.y) return; const wActor = window.get_compositor_private(); wActor && Main.wm._prepareAnimationInfo( global.window_manager, wActor, currRect, Meta.SizeChange.UNMAXIMIZE ); window.move_frame(false, x, y); } // Tile a window but ignore T-A features } else if ([Shortcuts.TOP_IGNORE_TA, Shortcuts.BOTTOM_IGNORE_TA, Shortcuts.LEFT_IGNORE_TA, Shortcuts.RIGHT_IGNORE_TA, Shortcuts.TOP_LEFT_IGNORE_TA, Shortcuts.TOP_RIGHT_IGNORE_TA, Shortcuts.BOTTOM_LEFT_IGNORE_TA, Shortcuts.BOTTOM_RIGHT_IGNORE_TA].includes(shortcutName) ) { const workArea = new Rect(window.get_work_area_current_monitor()); const rect = Twm.getDefaultTileFor(shortcutName, workArea); Twm.toggleTiling(window, rect, { ignoreTA: true }); // Tile a window } else { const dynamicBehavior = Settings.DYNAMIC_KEYBINDINGS; const dynamicSetting = Settings.getInt(dynamicBehavior); const windowsStyle = DynamicKeybindings.TILING_STATE_WINDOWS; const isWindowsStyle = dynamicSetting === windowsStyle; const workArea = new Rect(window.get_work_area_current_monitor()); const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); switch (dynamicSetting) { case DynamicKeybindings.FOCUS: this._dynamicFocus(window, shortcutName); break; case DynamicKeybindings.TILING_STATE: case DynamicKeybindings.TILING_STATE_WINDOWS: this._dynamicTilingState(window, shortcutName, isWindowsStyle); break; case DynamicKeybindings.FAVORITE_LAYOUT: this._dynamicFavoriteLayout(window, shortcutName); break; default: Twm.toggleTiling(window, rect); } } } /** * Tiles or moves the focus depending on the `windows` tiling state. * * @param {Meta.Window} window a Meta.Window as the starting position. * @param {string} shortcutName indicates the direction we tile or move * the focus to. */ _dynamicFocus(window, shortcutName) { const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true }); const workArea = new Rect(window.get_work_area_current_monitor()); // Toggle tile state of the window, if it isn't tiled // or if it is the only window which is. if (!window.isTiled || topTileGroup.length === 1) { const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; } let direction; switch (shortcutName) { case Shortcuts.MAXIMIZE: case Shortcuts.TOP: direction = Direction.N; break; case Shortcuts.BOTTOM: direction = Direction.S; break; case Shortcuts.LEFT: direction = Direction.W; break; case Shortcuts.RIGHT: direction = Direction.E; } const nearestWindow = Twm.getNearestWindow( window, topTileGroup, direction, false ); if (!nearestWindow) { const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; } // Activate() caused problems with an extensions' prefs window, if the // extensions-app wasn't open. nearestWindow.focus(global.get_current_time()); // Animation for visibility with a tmp 'tile preview' const fromRect = window.get_frame_rect(); const focusIndicator = new St.Widget({ style_class: 'tile-preview', opacity: 0, x: fromRect.x, y: fromRect.y, width: fromRect.width, height: fromRect.height }); Main.uiGroup.add_child(focusIndicator); const toRect = nearestWindow.get_frame_rect(); focusIndicator.ease({ opacity: 255, x: toRect.x, y: toRect.y, width: toRect.width, height: toRect.height, duration: 200, mode: Clutter.AnimationMode.EASE_OUT_QUART, onComplete: () => { focusIndicator.ease({ opacity: 0, duration: 200, mode: Clutter.AnimationMode.EASE_IN_OUT_CIRC, delay: 100, onComplete: () => focusIndicator.destroy() }); } }); } /** * Changes the tiling state of the `window` based on its current tiling * state and the activated shortcut. * * @param {Meta.Window} window a Meta.Window. * @param {string} shortcutName the shortcut. * @param {boolean} isWindowsStyle minimize when the `window` isn't tiled or * if it's tiled to the bottom and the 'tile to bottom' shortcut is * activated. */ _dynamicTilingState(window, shortcutName, isWindowsStyle) { const workArea = new Rect(window.get_work_area_current_monitor()); if (Twm.isMaximized(window)) { switch (shortcutName) { case Shortcuts.MAXIMIZE: case Shortcuts.TOP: { const rect = Twm.getTileFor(Shortcuts.TOP, workArea, window.get_monitor()); Twm.tile(window, rect, { skipAnim: true }); break; } case Shortcuts.BOTTOM: { Twm.untile(window); break; } default: { const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); } } return; } else if (!window.isTiled) { switch (shortcutName) { case Shortcuts.BOTTOM: { if (isWindowsStyle) { window.minimize(); break; } // falls through } default: { const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); } } return; } const wRect = window.tiledRect; const isLeftHalf = wRect.x === workArea.x && wRect.y === workArea.y && wRect.width !== workArea.width && wRect.height === workArea.height; const isRightHalf = wRect.x !== workArea.x && wRect.y === workArea.y && wRect.x2 === workArea.x2 && wRect.height === workArea.height; const isTopHalf = wRect.x === workArea.x && wRect.y === workArea.y && wRect.width === workArea.width && wRect.height !== workArea.height; const isBottomHalf = wRect.x === workArea.x && wRect.y !== workArea.y && wRect.width === workArea.width && wRect.y2 === workArea.y2; const isTopLeftQuarter = wRect.x === workArea.x && wRect.y === workArea.y && wRect.width !== workArea.width && wRect.height !== workArea.height; const isTopRightQuarter = wRect.x !== workArea.x && wRect.y === workArea.y && wRect.x2 === workArea.x2 && wRect.height !== workArea.height; const isBottomLeftQuarter = wRect.x === workArea.x && wRect.y !== workArea.y && wRect.width !== workArea.width && wRect.y2 === workArea.y2; const isBottomRightQuarter = wRect.x !== workArea.x && wRect.y !== workArea.y && wRect.x2 === workArea.x2 && wRect.y2 === workArea.y2; let rect; if (isLeftHalf) { switch (shortcutName) { case Shortcuts.TOP: case Shortcuts.MAXIMIZE: rect = Twm.getTileFor(Shortcuts.TOP_LEFT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.BOTTOM: rect = Twm.getTileFor(Shortcuts.BOTTOM_LEFT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.RIGHT: Twm.untile(window); return; } } else if (isRightHalf) { switch (shortcutName) { case Shortcuts.TOP: case Shortcuts.MAXIMIZE: rect = Twm.getTileFor(Shortcuts.TOP_RIGHT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.BOTTOM: rect = Twm.getTileFor(Shortcuts.BOTTOM_RIGHT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.LEFT: Twm.untile(window); return; } } else if (isTopHalf) { switch (shortcutName) { case Shortcuts.TOP: rect = Twm.getTileFor(Shortcuts.MAXIMIZE, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.LEFT: rect = Twm.getTileFor(Shortcuts.TOP_LEFT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.RIGHT: rect = Twm.getTileFor(Shortcuts.TOP_RIGHT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.BOTTOM: Twm.untile(window); return; } } else if (isBottomHalf) { switch (shortcutName) { case Shortcuts.LEFT: rect = Twm.getTileFor(Shortcuts.BOTTOM_LEFT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.RIGHT: rect = Twm.getTileFor(Shortcuts.BOTTOM_RIGHT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.TOP: case Shortcuts.MAXIMIZE: Twm.untile(window); return; case Shortcuts.BOTTOM: rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); isWindowsStyle ? window.minimize() : Twm.toggleTiling(window, rect); return; } } else if (isTopLeftQuarter) { switch (shortcutName) { case Shortcuts.RIGHT: rect = Twm.getTileFor(Shortcuts.TOP, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.BOTTOM: rect = Twm.getTileFor(Shortcuts.LEFT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; } } else if (isTopRightQuarter) { switch (shortcutName) { case Shortcuts.LEFT: rect = Twm.getTileFor(Shortcuts.TOP, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.BOTTOM: rect = Twm.getTileFor(Shortcuts.RIGHT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; } } else if (isBottomLeftQuarter) { switch (shortcutName) { case Shortcuts.TOP: case Shortcuts.MAXIMIZE: rect = Twm.getTileFor(Shortcuts.LEFT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.RIGHT: rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.BOTTOM: rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); isWindowsStyle ? window.minimize() : Twm.toggleTiling(window, rect); return; } } else if (isBottomRightQuarter) { switch (shortcutName) { case Shortcuts.TOP: case Shortcuts.MAXIMIZE: rect = Twm.getTileFor(Shortcuts.RIGHT, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.LEFT: rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); return; case Shortcuts.BOTTOM: rect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, window.get_monitor()); isWindowsStyle ? window.minimize() : Twm.toggleTiling(window, rect); return; } } Twm.toggleTiling(window, Twm.getTileFor(shortcutName, workArea, window.get_monitor())); } _dynamicFavoriteLayout(window, shortcutName) { const workArea = new Rect(window.get_work_area_current_monitor()); const toggleTiling = () => { const rect = Twm.getTileFor(shortcutName, workArea, window.get_monitor()); Twm.toggleTiling(window, rect); }; if (!window.isTiled) { toggleTiling(); return; } const favoriteLayout = Util.getFavoriteLayout(window.get_monitor()); if (favoriteLayout.length <= 1) { toggleTiling(); return; } let direction; switch (shortcutName) { case Shortcuts.TOP: case Shortcuts.MAXIMIZE: direction = Direction.N; break; case Shortcuts.BOTTOM: direction = Direction.S; break; case Shortcuts.LEFT: direction = Direction.W; break; case Shortcuts.RIGHT: direction = Direction.E; } if (direction) { const neighbor = window.tiledRect.getNeighbor(direction, favoriteLayout); Twm.tile(window, neighbor, { openTilingPopup: false }); } else { toggleTiling(); } } } Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/layoutsManager.js000066400000000000000000000504161457776040200313360ustar00rootroot00000000000000import { Clutter, Gio, GObject, Meta, Shell, St } from '../dependencies/gi.js'; import { _, Extension, Main, PanelMenu, PopupMenu } from '../dependencies/shell.js'; import { Layout, Settings } from '../common.js'; import { Rect, Util } from './utility.js'; import { TilingWindowManager as Twm } from './tilingWindowManager.js'; /** * Here are the classes to handle PopupLayouts on the shell / extension side. * See src/prefs/layoutsPrefs.js for more details and general info about layouts. * In summary, a Layout is an array of LayoutItems. A LayoutItem is a JS Object * and has a rect, an appId and a loopType. Only the rect is mandatory. AppId may * be null or a String. Same for the LoopType. If a layout is activated, we will * loop / step through each LayoutItem and spawn a Tiling Popup one after the * other for the rects and offer to tile a window to that rect. If an appId is * defined, instead of calling the Tiling Popup, we tile (a new Instance of) * the app to the rect. If a LoopType is defined, instead of going to the next * item / rect, we spawn a Tiling Popup on the same item / rect and all the * tiled windows will share that spot evenly (a la 'Master and Stack'). * * Additionally, there the user can select a 'favorite' layout among the * PopupLayouts. That layout will then be used as an fixed alternative mode to * the Edge Tiling. */ export default class TilingLayoutsManager { constructor() { // this._items is an array of LayoutItems (see explanation above). // this._currItem is 1 LayoutItem. A LayoutItem's rect only hold ratios // from 0 - 1. this._currRect is a Rect scaled to the workArea. this._items = []; this._currItem = null; this._currRect = null; // Preview to show where the window will tile to, similar // to the tile preview when dnding to the screen edges this._rectPreview = null; // Keep track of the windows which were already tiled with the current // layout and the remaining windows. Special-case windows, which were tiled // within a loop since they need to be re-adjusted for each new window // tiled to the same spot. The looped array is cleared after each 'step' / // LayoutItem change. this._tiledWithLayout = []; this._tiledWithLoop = []; this._remainingWindows = []; // Bind the keyboard shortcuts for each layout and the layout searchers this._keyBindings = []; for (let i = 0; i < 20; i++) { this._keyBindings.push(`activate-layout${i}`); Main.wm.addKeybinding( `activate-layout${i}`, Settings.getGioObject(), Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, Shell.ActionMode.NORMAL, this.startLayouting.bind(this, i) ); } this._keyBindings.push('search-popup-layout'); Main.wm.addKeybinding( 'search-popup-layout', Settings.getGioObject(), Meta.KeyBindingFlags.IGNORE_AUTOREPEAT, Shell.ActionMode.NORMAL, this.openPopupSearch.bind(this) ); // Add panel indicator this._panelIndicator = new PanelIndicator(); Main.panel.addToStatusArea( 'tiling-assistant@leleat-on-github', this._panelIndicator); this._settingsId = Settings.changed(Settings.SHOW_LAYOUT_INDICATOR, () => { this._panelIndicator.visible = Settings.getBoolean(Settings.SHOW_LAYOUT_INDICATOR); }); this._panelIndicator.visible = Settings.getBoolean(Settings.SHOW_LAYOUT_INDICATOR); this._panelIndicator.connect('layout-activated', (src, idx) => this.startLayouting(idx)); } destroy() { Settings.disconnect(this._settingsId); this._finishLayouting(); this._keyBindings.forEach(key => Main.wm.removeKeybinding(key)); this._panelIndicator.destroy(); this._panelIndicator = null; } /** * Opens a popup window so the user can activate a layout by name * instead of the keyboard shortcut. */ openPopupSearch() { const layouts = Util.getLayouts(); if (!layouts.length) { Main.notify('Tiling Assistant', _('No valid layouts defined.')); return; } const search = new LayoutSearch(layouts); search.connect('item-activated', (s, index) => this.startLayouting(index)); } /** * Starts tiling to a Popup Layout. * * @param {number} index the index of the layout we start tiling to. */ startLayouting(index) { const layout = Util.getLayouts()?.[index]; if (!layout) return; const allWs = Settings.getBoolean(Settings.POPUP_ALL_WORKSPACES); this._remainingWindows = Twm.getWindows(allWs); this._items = new Layout(layout).getItems(); this._currItem = null; const activeWs = global.workspace_manager.get_active_workspace(); const monitor = global.display.get_current_monitor(); const workArea = activeWs.get_work_area_for_monitor(monitor); this._rectPreview?.destroy(); this._rectPreview = new St.Widget({ style_class: 'tile-preview', opacity: 0, x: workArea.x + workArea.width / 2, y: workArea.y + workArea.height / 2 }); Main.layoutManager.addChrome(this._rectPreview); this._step(); } _finishLayouting() { this._items = []; this._currItem = null; this._currRect = null; this._rectPreview?.destroy(); this._rectPreview = null; this._tiledWithLayout = []; this._tiledWithLoop = []; this._remainingWindows = []; } _step(loopType = null) { // If we aren't looping on the current item, we need to prepare for the // step by getting the next item / rect. If we are looping, we stay on // the current item / rect and open a new Tiling Popup for that rect. if (!loopType) { // We're at the last item and not looping, so there are no more items. if (this._currItem === this._items.at(-1)) { this._finishLayouting(); return; } const currIdx = this._items.indexOf(this._currItem); this._currItem = this._items[currIdx + 1]; // Scale the item's rect to the workArea const activeWs = global.workspace_manager.get_active_workspace(); const monitor = global.display.get_current_monitor(); const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); const rectRatios = this._currItem.rect; this._currRect = new Rect( workArea.x + Math.floor(rectRatios.x * workArea.width), workArea.y + Math.floor(rectRatios.y * workArea.height), Math.ceil(rectRatios.width * workArea.width), Math.ceil(rectRatios.height * workArea.height) ); // Try to compensate possible rounding errors when scaling up the // rect by aligning it with the rects, which were already tiled // using this layout and the workArea. this._tiledWithLayout.forEach(w => this._currRect.tryAlignWith(w.tiledRect)); this._currRect.tryAlignWith(workArea); } const appId = this._currItem.appId; appId ? this._openAppTiled(appId) : this._openTilingPopup(); } _openAppTiled(appId) { const app = Shell.AppSystem.get_default().lookup_app(appId); if (!app) { Main.notify('Tiling Assistant', _('Popup Layouts: App not found.')); this._finishLayouting(); return; } const winTracker = Shell.WindowTracker.get_default(); const idx = this._remainingWindows.findIndex(w => winTracker.get_window_app(w) === app); const window = this._remainingWindows[idx]; idx !== -1 && this._remainingWindows.splice(idx, 1); if (window) { Twm.tile(window, this._currRect, { openTilingPopup: false, skipAnim: true }); } else if (app.can_open_new_window()) { Twm.openAppTiled(app, this._currRect); } this._step(); } async _openTilingPopup() { // There are no open windows left to tile using the Tiling Popup. // However there may be items with appIds, which we want to open. // So continue... if (!this._remainingWindows.length) { this._step(); return; } // Animate the rect preview this._rectPreview.ease({ x: this._currRect.x, y: this._currRect.y, width: this._currRect.width, height: this._currRect.height, opacity: 255, duration: 200, mode: Clutter.AnimationMode.EASE_OUT_QUAD }); // Create the Tiling Popup const TilingPopup = await import('./tilingPopup.js'); const popup = new TilingPopup.TilingSwitcherPopup( this._remainingWindows, this._currRect, // If this._currItem is the last item and we don't loop over it, // allow the Tiling Popup itself to spawn another instance of // a Tiling Popup, if there is free screen space. this._currItem === this._items.at(-1) && !this._currItem.loopType, true ); const stacked = global.display.sort_windows_by_stacking(this._tiledWithLayout); const tileGroup = stacked.reverse(); if (!popup.show(tileGroup)) { popup.destroy(); this._finishLayouting(); return; } popup.connect('closed', this._onTilingPopupClosed.bind(this)); } _onTilingPopupClosed(tilingPopup, canceled) { if (canceled) { if (this._currItem.loopType) { this._tiledWithLoop = []; this._step(); } else { this._finishLayouting(); } } else { const tiledWindow = tilingPopup.tiledWindow; this._tiledWithLayout.push(tiledWindow); const i = this._remainingWindows.indexOf(tiledWindow); this._remainingWindows.splice(i, 1); // Make all windows, which were tiled during the current loop, // share the current rect evenly -> like the 'Stack' part of a // 'Master and Stack' if (this._currItem.loopType) { this._tiledWithLoop.push(tiledWindow); this._tiledWithLoop.forEach((w, idx) => { const rect = this._currRect.copy(); const [pos, dimension] = this._currItem.loopType === 'h' ? ['y', 'height'] : ['x', 'width']; rect[dimension] /= this._tiledWithLoop.length; rect[pos] += idx * rect[dimension]; Twm.tile(w, rect, { openTilingPopup: false, skipAnim: true }); }); } this._step(this._currItem.loopType); } } } /** * The GUI class for the Layout search. */ const LayoutSearch = GObject.registerClass({ Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] } } }, class TilingLayoutsSearch extends St.Widget { _init(layouts) { const activeWs = global.workspace_manager.get_active_workspace(); super._init({ reactive: true, x: Main.uiGroup.x, y: Main.uiGroup.y, width: Main.uiGroup.width, height: Main.uiGroup.height }); Main.uiGroup.add_child(this); const grab = Main.pushModal(this); // We expect at least a keyboard grab here if ((grab.get_seat_state() & Clutter.GrabState.KEYBOARD) === 0) { Main.popModal(grab); return false; } this._grab = grab; this._haveModal = true; this._focused = -1; this._items = []; this.connect('button-press-event', () => this.destroy()); const popup = new St.BoxLayout({ style_class: 'switcher-list', vertical: true, width: 500 }); this.add_child(popup); const fontSize = 16; const entry = new St.Entry({ style: `font-size: ${fontSize}px;\ border-radius: 16px; margin-bottom: 12px;`, // The cursor overlaps the text, so add some spaces at the beginning hint_text: ` ${_('Type to search...')}` }); const entryClutterText = entry.get_clutter_text(); entryClutterText.connect('key-press-event', this._onKeyPressed.bind(this)); entryClutterText.connect('text-changed', this._onTextChanged.bind(this)); popup.add_child(entry); this._items = layouts.map(layout => { const item = new SearchItem(layout._name, fontSize); item.connect('button-press-event', this._onItemClicked.bind(this)); popup.add_child(item); return item; }); if (!this._items.length) { this.destroy(); return; } const monitor = global.display.get_current_monitor(); const workArea = activeWs.get_work_area_for_monitor(monitor); popup.set_position(workArea.x + workArea.width / 2 - popup.width / 2, workArea.y + workArea.height / 2 - popup.height / 2); entry.grab_key_focus(); this._focus(0); } destroy() { if (this._haveModal) { Main.popModal(this._grab); this._haveModal = false; } super.destroy(); } _onKeyPressed(clutterText, event) { const keySym = event.get_key_symbol(); if (keySym === Clutter.KEY_Escape) { this.destroy(); return Clutter.EVENT_STOP; } else if (keySym === Clutter.KEY_Return || keySym === Clutter.KEY_KP_Enter || keySym === Clutter.KEY_ISO_Enter) { this._activate(); return Clutter.EVENT_STOP; } else if (keySym === Clutter.KEY_Down) { this._focusNext(); return Clutter.EVENT_STOP; } else if (keySym === Clutter.KEY_Up) { this._focusPrev(); return Clutter.EVENT_STOP; } return Clutter.EVENT_PROPAGATE; } _onTextChanged(clutterText) { const filterText = clutterText.get_text(); this._items.forEach(item => { item.text.toLowerCase().includes(filterText.toLowerCase()) ? item.show() : item.hide(); }); const nextVisibleIdx = this._items.findIndex(item => item.visible); this._focus(nextVisibleIdx); } _onItemClicked(item) { this._focused = this._items.indexOf(item); this._activate(); } _focusPrev() { this._focus((this._focused + this._items.length - 1) % this._items.length); } _focusNext() { this._focus((this._focused + 1) % this._items.length); } _focus(newIdx) { const prevItem = this._items[this._focused]; const newItem = this._items[newIdx]; this._focused = newIdx; prevItem?.remove_style_class_name('tiling-layout-search-highlight'); newItem?.add_style_class_name('tiling-layout-search-highlight'); } _activate() { this._focused !== -1 && this.emit('item-activated', this._focused); this.destroy(); } }); /** * An Item representing a Layout within the Popup Layout search. */ const SearchItem = GObject.registerClass( class TilingLayoutsSearchItem extends St.Label { _init(text, fontSize) { super._init({ // Add some spaces to the beginning to align it better // with the rounded corners text: ` ${text || _('Nameless layout...')}`, style: `font-size: ${fontSize}px;\ text-align: left;\ padding: 8px\ margin-bottom: 2px`, reactive: true }); } }); /** * A panel indicator to activate and favoritize a layout. */ const PanelIndicator = GObject.registerClass({ Signals: { 'layout-activated': { param_types: [GObject.TYPE_INT] } } }, class PanelIndicator extends PanelMenu.Button { _init() { super._init(0.0, 'Layout Indicator (Tiling Assistant)'); const path = Extension.lookupByURL(import.meta.url) .dir .get_child('media/preferences-desktop-apps-symbolic.svg') .get_path(); const gicon = new Gio.FileIcon({ file: Gio.File.new_for_path(path) }); this.add_child(new St.Icon({ gicon, style_class: 'system-status-icon' })); const menuAlignment = 0.0; this.setMenu(new PopupMenu.PopupMenu(this, menuAlignment, St.Side.TOP)); } vfunc_event(event) { if (this.menu && (event.type() === Clutter.EventType.TOUCH_BEGIN || event.type() === Clutter.EventType.BUTTON_PRESS) ) { this._updateItems(); this.menu.toggle(); } return Clutter.EVENT_PROPAGATE; } _updateItems() { this.menu.removeAll(); const layouts = Util.getLayouts(); if (!layouts.length) { const item = new PopupMenu.PopupMenuItem(_('No valid layouts defined.')); item.setSensitive(false); this.menu.addMenuItem(item); } else { // Update favorites with monitor count and fill with '-1', if necessary const tmp = Settings.getStrv(Settings.FAVORITE_LAYOUTS); const count = Math.max(Main.layoutManager.monitors.length, tmp.length); const favorites = [...new Array(count)].map((m, monitorIndex) => { return tmp[monitorIndex] ?? '-1'; }); Settings.setStrv(Settings.FAVORITE_LAYOUTS, favorites); // Create popup menu items layouts.forEach((layout, idx) => { const name = layout._name || `Layout ${idx + 1}`; const item = new PopupFavoriteMenuItem(name, idx); item.connect('activate', () => { Main.overview.hide(); this.emit('layout-activated', idx); }); item.connect('favorite-changed', this._updateItems.bind(this)); this.menu.addMenuItem(item); }); } this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); const settingsButton = new PopupMenu.PopupImageMenuItem('Preferences', 'emblem-system-symbolic'); // Center button without changing the size (for the hover highlight) settingsButton._icon.set_x_expand(true); settingsButton.label.set_x_expand(true); settingsButton.connect('activate', () => Extension.lookupByURL(import.meta.url).openPreferences()); this.menu.addMenuItem(settingsButton); } }); /** * A PopupMenuItem for the PopupMenu of the PanelIndicator. */ const PopupFavoriteMenuItem = GObject.registerClass({ Signals: { 'favorite-changed': { param_types: [GObject.TYPE_INT] } } }, class PopupFavoriteMenuItem extends PopupMenu.PopupBaseMenuItem { _init(text, layoutIndex) { super._init(); this.add_child(new St.Label({ text, x_expand: true })); const favorites = Settings.getStrv(Settings.FAVORITE_LAYOUTS); Main.layoutManager.monitors.forEach((m, monitorIndex) => { const favoriteButton = new St.Button({ child: new St.Icon({ icon_name: favorites[monitorIndex] === `${layoutIndex}` ? 'starred-symbolic' : 'non-starred-symbolic', style_class: 'popup-menu-icon' }) }); this.add_child(favoriteButton); // Update gSetting with new Favorite (act as a toggle button) favoriteButton.connect('clicked', () => { const currFavorites = Settings.getStrv(Settings.FAVORITE_LAYOUTS); currFavorites[monitorIndex] = currFavorites[monitorIndex] === `${layoutIndex}` ? '-1' : `${layoutIndex}`; Settings.setStrv(Settings.FAVORITE_LAYOUTS, currFavorites); this.emit('favorite-changed', monitorIndex); }); }); } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/moveHandler.js000066400000000000000000001202001457776040200305740ustar00rootroot00000000000000import { Clutter, GLib, GObject, Gio, Meta, Mtk } from '../dependencies/gi.js'; import { Main, WindowManager } from '../dependencies/shell.js'; import { WINDOW_ANIMATION_TIME } from '../dependencies/unexported/windowManager.js'; import { Orientation, RestoreOn, MoveModes, Settings, Shortcuts } from '../common.js'; import { Rect, Util } from './utility.js'; import { TilingWindowManager as Twm } from './tilingWindowManager.js'; /** * This class gets to handle the move events (grab & monitor change) of windows. * If the moved window is tiled at the start of the grab, untile it. This is * done by releasing the grab via code, resizing the window, and then restarting * the grab via code. On Wayland this may not be reliable. As a workaround there * is a setting to restore a tiled window's size on the actual grab end. */ export default class TilingMoveHandler { constructor() { const moveOps = [Meta.GrabOp.MOVING, Meta.GrabOp.KEYBOARD_MOVING]; this._displaySignals = []; const g1Id = global.display.connect('grab-op-begin', (src, window, grabOp) => { grabOp &= ~1024; // META_GRAB_OP_WINDOW_FLAG_UNCONSTRAINED if (window && moveOps.includes(grabOp)) this._onMoveStarted(window, grabOp); }); this._displaySignals.push(g1Id); const wId = global.display.connect('window-entered-monitor', this._onMonitorEntered.bind(this)); this._displaySignals.push(wId); // Save the windows, which need to make space for the // grabbed window (this is for the so called 'adaptive mode'): // { window1: newTileRect1, window2: newTileRect2, ... } this._splitRects = new Map(); // The rect the grabbed window will tile to // (it may differ from the tilePreview's rect) this._tileRect = null; this._favoritePreviews = []; this._tilePreview = new TilePreview(); // The mouse button mod to move/resize a window may be changed to Alt. // So switch Alt and Super in our own prefs, if the user switched from // Super to Alt. const modKeys = [ Settings.ADAPTIVE_TILING_MOD, Settings.FAVORITE_LAYOUT_MOD, Settings.IGNORE_TA_MOD ]; const handleWindowActionKeyConflict = () => { const currMod = this._wmPrefs.get_string('mouse-button-modifier'); if (currMod === '') { for (const key of modKeys) { const mod = Settings.getInt(key); if (mod === 2) // Alt Settings.setInt(key, 0); } } else if (currMod === '') { for (const key of modKeys) { const mod = Settings.getInt(key); if (mod === 4) // Super Settings.setInt(key, 0); } } }; this._wmPrefs = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); this._wmPrefs.connectObject( 'changed::mouse-button-modifier', () => handleWindowActionKeyConflict(), this ); handleWindowActionKeyConflict(); } destroy() { this._wmPrefs.disconnectObject(this); this._wmPrefs = null; this._displaySignals.forEach(sId => global.display.disconnect(sId)); this._tilePreview.destroy(); if (this._latestMonitorLockTimerId) { GLib.Source.remove(this._latestMonitorLockTimerId); this._latestMonitorLockTimerId = null; } if (this._latestPreviewTimerId) { GLib.Source.remove(this._latestPreviewTimerId); this._latestPreviewTimerId = null; } if (this._cursorChangeTimerId) { GLib.Source.remove(this._cursorChangeTimerId); this._cursorChangeTimerId = null; } if (this._restoreSizeTimerId) { GLib.Source.remove(this._restoreSizeTimerId); this._restoreSizeTimerId = null; } if (this._movingTimerId) { GLib.Source.remove(this._movingTimerId); this._movingTimerId = null; } } _onMonitorEntered(src, monitorNr, window) { if (this._isGrabOp) // Reset preview mode: // Currently only needed to grab the favorite layout for the new monitor. this._preparePreviewModeChange(this._currPreviewMode, window); } _onMoveStarted(window, grabOp) { // Also work with a window, which was maximized by GNOME natively // because it may have been tiled with this extension before being // maximized so we need to restore its size to pre-tiling. this._wasMaximizedOnStart = window.get_maximized(); const [x, y] = global.get_pointer(); // Try to restore the window size const restoreSetting = Settings.getInt(Settings.RESTORE_SIZE_ON); if ((window.tiledRect || this._wasMaximizedOnStart) && restoreSetting === RestoreOn.ON_GRAB_START ) { // HACK: // The grab begin signal (and thus this function call) gets fired // at the moment of the first click. However I don't want to restore // the window size on just a click. Only if the user actually wanted // to start a grab i.e. if the click is held for a bit or if the // cursor moved while holding the click. I assume a cursor change // means the grab was released since I couldn't find a better way... let grabReleased = false; let cursorId = global.display.connect('cursor-updated', () => { grabReleased = true; cursorId && global.display.disconnect(cursorId); cursorId = 0; }); // Clean up in case my assumption mentioned above is wrong // and the cursor never gets updated or something else... this._cursorChangeTimerId && GLib.Source.remove(this._cursorChangeTimerId); this._cursorChangeTimerId = GLib.timeout_add(GLib.PRIORITY_LOW, 400, () => { cursorId && global.display.disconnect(cursorId); cursorId = 0; this._cursorChangeTimerId = null; return GLib.SOURCE_REMOVE; }); let counter = 0; this._restoreSizeTimerId && GLib.Source.remove(this._restoreSizeTimerId); this._restoreSizeTimerId = GLib.timeout_add(GLib.PRIORITY_HIGH_IDLE, 10, () => { if (grabReleased) { this._restoreSizeTimerId = null; return GLib.SOURCE_REMOVE; } counter += 10; if (counter >= 400) { this._restoreSizeAndRestartGrab(window, x, y, grabOp); this._restoreSizeTimerId = null; return GLib.SOURCE_REMOVE; } const [currX, currY] = global.get_pointer(); const currPoint = { x: currX, y: currY }; const oldPoint = { x, y }; const moveDist = Util.getDistance(currPoint, oldPoint); if (moveDist > 10) { this._restoreSizeAndRestartGrab(window, x, y, grabOp); this._restoreSizeTimerId = null; return GLib.SOURCE_REMOVE; } return GLib.SOURCE_CONTINUE; }); // Tile preview } else { this._isGrabOp = true; this._monitorNr = global.display.get_current_monitor(); this._lastMonitorNr = this._monitorNr; this._lastPointerPos = { x, y }; this._pointerDidntMove = false; this._movingTimerDuration = 20; this._movingTimeoutsSinceUpdate = 0; this._topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true }); // When low performance mode is enabled we use a timer to periodically // update the tile previews so that we don't update the tile preview // as often when compared to the position-changed signal. if (Settings.getBoolean(Settings.LOW_PERFORMANCE_MOVE_MODE)) { this._movingTimerId = GLib.timeout_add( GLib.PRIORITY_IDLE, this._movingTimerDuration, this._onMoving.bind( this, grabOp, window, true ) ); const id = global.display.connect('grab-op-end', () => { global.display.disconnect(id); // 'Quick throws' of windows won't create a tile preview since // the timeout for onMoving may not have happened yet. So force // 1 call of the tile preview updates for those quick actions. this._onMoving(grabOp, window); this._onMoveFinished(window); }); // Otherwise we will update the tile preview whenever the window is // moved as often as necessary. } else { this._posChangedId = window.connect('position-changed', this._onMoving.bind( this, grabOp, window, false ) ); const id = global.display.connect('grab-op-end', () => { global.display.disconnect(id); this._onMoveFinished(window); }); } } } _onMoveFinished(window) { if (this._posChangedId) { window.disconnect(this._posChangedId); this._posChangedId = 0; } if (this._tileRect) { // Ctrl-drag to replace some windows in a tile group / create a new tile group // with at least 1 window being part of multiple tile groups. let isCtrlReplacement = false; const ctrlReplacedTileGroup = []; const topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true }); const pointerPos = { x: global.get_pointer()[0], y: global.get_pointer()[1] }; const twHovered = topTileGroup.some(w => w.tiledRect.containsPoint(pointerPos)); if (this._currPreviewMode === MoveModes.ADAPTIVE_TILING && !this._splitRects.size && twHovered) { isCtrlReplacement = true; ctrlReplacedTileGroup.push(window); topTileGroup.forEach(w => { if (!this._tileRect.containsRect(w.tiledRect)) ctrlReplacedTileGroup.push(w); }); } this._splitRects.forEach((rect, w) => Twm.tile(w, rect, { openTilingPopup: false })); this._splitRects.clear(); Twm.tile(window, this._tileRect, { monitorNr: this._monitorNr, openTilingPopup: this._currPreviewMode !== MoveModes.ADAPTIVE_TILING, ignoreTA: this._ignoreTA }); this._tileRect = null; // Create a new tile group, in which some windows are already part // of a different tile group, with ctrl-(super)-drag. The window may // be maximized by ctrl-super-drag. isCtrlReplacement && window.isTiled && Twm.updateTileGroup(ctrlReplacedTileGroup); } else { const restoreSetting = Settings.getInt(Settings.RESTORE_SIZE_ON); const restoreOnEnd = restoreSetting === RestoreOn.ON_GRAB_END; restoreOnEnd && Twm.untile( window, { restoreFullPos: false, xAnchor: this._lastPointerPos.x, skipAnim: this._wasMaximizedOnStart } ); } this._favoriteLayout = []; this._favoritePreviews?.forEach(p => p.destroy()); this._favoritePreviews = []; this._freeScreenRects = []; this._anchorRect = null; this._topTileGroup = null; this._tilePreview.close(); this._currPreviewMode = MoveModes.ADAPTIVE_TILING; this._isGrabOp = false; } // If lowPerfMode is enabled in the settings: // Called periodically (~ every 20 ms) with a timer after a window was grabbed. // However this function will only update the tile previews fully after about // 500 ms. Force an earlier update, if the pointer movement state changed // (e.g. pointer came to a stop after a movement). This Detection is done // naively by comparing the pointer position of the previous timeout with // the current position. // Without the lowPerfMode enabled this will be called whenever the window is // moved (by listening to the position-changed signal) _onMoving(grabOp, window, lowPerfMode = false) { const [x, y] = global.get_pointer(); const currPointerPos = { x, y }; if (lowPerfMode) { if (!this._isGrabOp) { this._movingTimerId = null; return GLib.SOURCE_REMOVE; } const movementDist = Util.getDistance(this._lastPointerPos, currPointerPos); const movementDetectionThreshold = 10; let forceMoveUpdate = false; this._movingTimeoutsSinceUpdate++; // Force an early update if the movement state changed // i. e. moving -> stand still or stand still -> moving if (this._pointerDidntMove) { if (movementDist > movementDetectionThreshold) { this._pointerDidntMove = false; forceMoveUpdate = true; } } else if (movementDist < movementDetectionThreshold) { this._pointerDidntMove = true; forceMoveUpdate = true; } // Only update the tile preview every 500 ms for better performance. // Force an early update, if the pointer movement state changed. const updateInterval = 500; const timeSinceLastUpdate = this._movingTimerDuration * this._movingTimeoutsSinceUpdate; if (timeSinceLastUpdate < updateInterval && !forceMoveUpdate) return GLib.SOURCE_CONTINUE; this._movingTimeoutsSinceUpdate = 0; } this._lastPointerPos = currPointerPos; const ctrl = Clutter.ModifierType.CONTROL_MASK; const altL = Clutter.ModifierType.MOD1_MASK; const altGr = Clutter.ModifierType.MOD5_MASK; const meta = Clutter.ModifierType.MOD4_MASK; const rmb = Meta.is_wayland_compositor() ? Clutter.ModifierType.BUTTON2_MASK : Clutter.ModifierType.BUTTON3_MASK; const pressed = [ // idxs come from settings false, // Dummy for disabled state so that we can use the correct idxs Util.isModPressed(ctrl), Util.isModPressed(altL) || Util.isModPressed(altGr), Util.isModPressed(rmb), Util.isModPressed(meta) ]; const defaultMode = Settings.getInt(Settings.DEFAULT_MOVE_MODE); const adaptiveMod = Settings.getInt(Settings.ADAPTIVE_TILING_MOD); const favMod = Settings.getInt(Settings.FAVORITE_LAYOUT_MOD); const ignoreTAMod = Settings.getInt(Settings.IGNORE_TA_MOD); const noMod = pressed.every(modPressed => !modPressed); const useAdaptiveTiling = defaultMode !== MoveModes.ADAPTIVE_TILING && adaptiveMod && pressed[adaptiveMod] || noMod && defaultMode === MoveModes.ADAPTIVE_TILING; const usefavLayout = defaultMode !== MoveModes.FAVORITE_LAYOUT && favMod && pressed[favMod] || noMod && defaultMode === MoveModes.FAVORITE_LAYOUT; const useIgnoreTa = defaultMode !== MoveModes.IGNORE_TA && ignoreTAMod && pressed[ignoreTAMod] || noMod && defaultMode === MoveModes.IGNORE_TA; let newMode = ''; if (useAdaptiveTiling) newMode = MoveModes.ADAPTIVE_TILING; else if (usefavLayout) newMode = MoveModes.FAVORITE_LAYOUT; else if (useIgnoreTa) newMode = MoveModes.IGNORE_TA; else newMode = MoveModes.EDGE_TILING; if (this._currPreviewMode !== newMode) this._preparePreviewModeChange(newMode, window); switch (newMode) { case MoveModes.IGNORE_TA: case MoveModes.EDGE_TILING: this._edgeTilingPreview(window, grabOp); break; case MoveModes.ADAPTIVE_TILING: this._adaptiveTilingPreview(window, grabOp); break; case MoveModes.FAVORITE_LAYOUT: this._favoriteLayoutTilingPreview(window); } this._currPreviewMode = newMode; return GLib.SOURCE_CONTINUE; } _preparePreviewModeChange(newMode, window) { this._tileRect = null; this._ignoreTA = false; this._topTileGroup = Twm.getTopTileGroup({ skipTopWindow: true }); const activeWs = global.workspace_manager.get_active_workspace(); const monitor = global.display.get_current_monitor(); const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); const tRects = this._topTileGroup.map(w => w.tiledRect); this._freeScreenRects = workArea.minus(tRects); switch (this._currPreviewMode) { case MoveModes.ADAPTIVE_TILING: this._monitorNr = global.display.get_current_monitor(); this._splitRects.clear(); this._anchorRect = null; break; case MoveModes.FAVORITE_LAYOUT: this._monitorNr = global.display.get_current_monitor(); this._favoritePreviews.forEach(p => { p.ease({ opacity: 0, duration: 100, mode: Clutter.AnimationMode.EASE_OUT_QUAD, onComplete: () => p.destroy() }); }); this._favoritePreviews = []; this._anchorRect = null; } switch (newMode) { case MoveModes.IGNORE_TA: this._ignoreTA = true; break; case MoveModes.FAVORITE_LAYOUT: this._favoriteLayout = Util.getFavoriteLayout(); this._favoriteLayout.forEach(rect => { const tilePreview = new TilePreview(); tilePreview.open(window, rect, this._monitorNr, { opacity: 255, duration: 150 }); this._favoritePreviews.push(tilePreview); }); } } _restoreSizeAndRestartGrab(window, px, py, grabOp) { Twm.untile(window, { restoreFullPos: false, xAnchor: px, skipAnim: this._wasMaximizedOnStart }); this._onMoveStarted(window, grabOp); } /** * Previews the rect the `window` will tile to when moving along the * screen edges. * * @param {Meta.Window} window the grabbed Meta.Window. * @param {Meta.GrabOp} grabOp the current Meta.GrabOp. */ _edgeTilingPreview(window, grabOp) { // When switching monitors, provide a short grace period // in which the tile preview will stick to the old monitor so that // the user doesn't have to slowly inch the mouse to the monitor edge // just because there is another monitor at that edge. const currMonitorNr = global.display.get_current_monitor(); const useGracePeriod = Settings.getBoolean(Settings.MONITOR_SWITCH_GRACE_PERIOD); if (useGracePeriod) { if (this._lastMonitorNr !== currMonitorNr) { this._monitorNr = this._lastMonitorNr; let timerId = 0; this._latestMonitorLockTimerId && GLib.Source.remove(this._latestMonitorLockTimerId); this._latestMonitorLockTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, () => { // Only update the monitorNr, if the latest timer timed out. if (timerId === this._latestMonitorLockTimerId) { this._monitorNr = global.display.get_current_monitor(); if (global.display.is_grabbed?.() || global.display.get_grab_op?.() === grabOp) // ! this._edgeTilingPreview(window, grabOp); } this._latestMonitorLockTimerId = null; return GLib.SOURCE_REMOVE; }); timerId = this._latestMonitorLockTimerId; } } else { this._monitorNr = global.display.get_current_monitor(); } this._lastMonitorNr = currMonitorNr; const wRect = window.get_frame_rect(); const workArea = new Rect(window.get_work_area_for_monitor(this._monitorNr)); const vDetectionSize = Settings.getInt(Settings.VERTICAL_PREVIEW_AREA); const pointerAtTopEdge = this._lastPointerPos.y <= workArea.y + vDetectionSize; const pointerAtBottomEdge = this._lastPointerPos.y >= workArea.y2 - vDetectionSize; const hDetectionSize = Settings.getInt(Settings.HORIZONTAL_PREVIEW_AREA); const pointerAtLeftEdge = this._lastPointerPos.x <= workArea.x + hDetectionSize; const pointerAtRightEdge = this._lastPointerPos.x >= workArea.x2 - hDetectionSize; // Also use window's pos for top and bottom area detection for quarters // because global.get_pointer's y isn't accurate (no idea why...) when // grabbing the titlebar & slowly going from the left/right sides to // the top/bottom corners. const titleBarGrabbed = this._lastPointerPos.y - wRect.y < 50; const windowAtTopEdge = titleBarGrabbed && wRect.y === workArea.y; const windowAtBottomEdge = wRect.y >= workArea.y2 - 75; const tileTopLeftQuarter = pointerAtLeftEdge && (pointerAtTopEdge || windowAtTopEdge); const tileTopRightQuarter = pointerAtRightEdge && (pointerAtTopEdge || windowAtTopEdge); const tileBottomLeftQuarter = pointerAtLeftEdge && (pointerAtBottomEdge || windowAtBottomEdge); const tileBottomRightQuarter = pointerAtRightEdge && (pointerAtBottomEdge || windowAtBottomEdge); if (tileTopLeftQuarter) { this._tileRect = Twm.getTileFor(Shortcuts.TOP_LEFT, workArea, this._monitorNr); this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); } else if (tileTopRightQuarter) { this._tileRect = Twm.getTileFor(Shortcuts.TOP_RIGHT, workArea, this._monitorNr); this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); } else if (tileBottomLeftQuarter) { this._tileRect = Twm.getTileFor(Shortcuts.BOTTOM_LEFT, workArea, this._monitorNr); this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); } else if (tileBottomRightQuarter) { this._tileRect = Twm.getTileFor(Shortcuts.BOTTOM_RIGHT, workArea, this._monitorNr); this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); } else if (pointerAtTopEdge) { // Switch between maximize & top tiling when keeping the mouse at the top edge. const monitorRect = global.display.get_monitor_geometry(this._monitorNr); const isLandscape = monitorRect.width >= monitorRect.height; const shouldMaximize = isLandscape && !Settings.getBoolean(Settings.ENABLE_HOLD_INVERSE_LANDSCAPE) || !isLandscape && !Settings.getBoolean(Settings.ENABLE_HOLD_INVERSE_PORTRAIT); const tileRect = shouldMaximize ? workArea : Twm.getTileFor(Shortcuts.TOP, workArea, this._monitorNr); const holdTileRect = shouldMaximize ? Twm.getTileFor(Shortcuts.TOP, workArea, this._monitorNr) : workArea; // Dont open preview / start new timer if preview was already one for the top if (this._tilePreview._rect && (holdTileRect.equal(this._tilePreview._rect) || this._tilePreview._rect.equal(tileRect.meta))) return; this._tileRect = tileRect; this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); let timerId = 0; this._latestPreviewTimerId && GLib.Source.remove(this._latestPreviewTimerId); this._latestPreviewTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, Settings.getInt(Settings.INVERSE_TOP_MAXIMIZE_TIMER), () => { // Only open the alternative preview, if the timeout-ed timer // is the same as the one which started last if (timerId === this._latestPreviewTimerId && this._tilePreview._showing && this._tilePreview._rect.equal(tileRect.meta)) { this._tileRect = holdTileRect; this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); } this._latestPreviewTimerId = null; return GLib.SOURCE_REMOVE; }); timerId = this._latestPreviewTimerId; } else if (pointerAtBottomEdge) { this._tileRect = Twm.getTileFor(Shortcuts.BOTTOM, workArea, this._monitorNr); this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); } else if (pointerAtLeftEdge) { this._tileRect = Twm.getTileFor(Shortcuts.LEFT, workArea, this._monitorNr); this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); } else if (pointerAtRightEdge) { this._tileRect = Twm.getTileFor(Shortcuts.RIGHT, workArea, this._monitorNr); this._tilePreview.open(window, this._tileRect.meta, this._monitorNr); } else { this._tileRect = null; this._tilePreview.close(); } } /** * Activates the secondary preview mode. By default, it's activated with * `Ctrl`. When tiling using this mode, it will not only affect the grabbed * window but possibly others as well. It's split into a 'single' and a * 'group' mode. Take a look at _adaptiveTilingPreviewSingle() and * _adaptiveTilingPreviewGroup() for details. * * @param {Meta.Window} window * @param {Meta.GrabOp} grabOp */ _adaptiveTilingPreview(window, grabOp) { if (!this._topTileGroup.length) { this._edgeTilingPreview(window, grabOp); return; } const screenRects = this._topTileGroup .map(w => w.tiledRect) .concat(this._freeScreenRects); const hoveredRect = screenRects.find(r => r.containsPoint(this._lastPointerPos)); if (!hoveredRect) { this._tilePreview.close(); this._tileRect = null; return; } const isSuperPressed = Util.isModPressed(Clutter.ModifierType.MOD4_MASK); if (isSuperPressed) { this._anchorRect = this._anchorRect ?? hoveredRect; this._tileRect = hoveredRect.union(this._anchorRect); this._splitRects.clear(); this._tilePreview.open(window, this._tileRect.meta, this._monitorNr, { x: this._tileRect.x, y: this._tileRect.y, width: this._tileRect.width, height: this._tileRect.height, opacity: 200 }); } else { this._anchorRect = null; const edgeRadius = 50; const atTopEdge = this._lastPointerPos.y < hoveredRect.y + edgeRadius; const atBottomEdge = this._lastPointerPos.y > hoveredRect.y2 - edgeRadius; const atLeftEdge = this._lastPointerPos.x < hoveredRect.x + edgeRadius; const atRightEdge = this._lastPointerPos.x > hoveredRect.x2 - edgeRadius; atTopEdge || atBottomEdge || atLeftEdge || atRightEdge ? this._adaptiveTilingPreviewGroup(window, hoveredRect, { atTopEdge, atBottomEdge, atLeftEdge, atRightEdge }) : this._adaptiveTilingPreviewSingle(window, hoveredRect); } } /** * In this mode, when moving a window over a tiled window, the tilePreview * will appear and (partly) cover the tiled window. If your pointer is at * the center, the grabbed window will just tile over the hovered tiled * window. If your pointer is hovering over the sides (but not the very * edges) of the tiled window, the tilePreview will only cover half of the * tiled window. Once the grabbed window is tiled, the previously hovered * tiled window, will make space for the grabbed window by halving its size. * * @param {Meta.Window} window * @param {Rect} hoveredRect */ _adaptiveTilingPreviewSingle(window, hoveredRect) { const atTop = this._lastPointerPos.y < hoveredRect.y + hoveredRect.height * .25; const atBottom = this._lastPointerPos.y > hoveredRect.y + hoveredRect.height * .75; const atRight = this._lastPointerPos.x > hoveredRect.x + hoveredRect.width * .75; const atLeft = this._lastPointerPos.x < hoveredRect.x + hoveredRect.width * .25; const splitVertically = atTop || atBottom; const splitHorizontally = atLeft || atRight; if (splitHorizontally || splitVertically) { const idx = atTop && !atRight || atLeft ? 0 : 1; const size = splitHorizontally ? hoveredRect.width : hoveredRect.height; const orientation = splitHorizontally ? Orientation.V : Orientation.H; this._tileRect = hoveredRect.getUnitAt(idx, size / 2, orientation); } else { this._tileRect = hoveredRect.copy(); } if (!this._tilePreview.needsUpdate(this._tileRect)) return; const monitor = global.display.get_current_monitor(); this._tilePreview.open(window, this._tileRect.meta, monitor); this._splitRects.clear(); const hoveredWindow = this._topTileGroup.find(w => { return w.tiledRect.containsPoint(this._lastPointerPos); }); if (!hoveredWindow) return; // Don't halve the window, if we compelety cover it i. e. // the user is hovering the tiled window at the center. if (hoveredWindow.tiledRect.equal(this._tileRect)) return; const splitRect = hoveredWindow.tiledRect.minus(this._tileRect)[0]; this._splitRects.set(hoveredWindow, splitRect); } /** * Similar to _adaptiveTilingPreviewSingle(). But it's activated by hovering * the very edges of a tiled window. And instead of affecting just 1 window * it can possibly re-tile multiple windows. A tiled window will be affected, * if it aligns with the edge that is being hovered. It's probably easier * to understand, if you see it in action first rather than reading about it. * * @param {Meta.Window} window * @param {Rect} hoveredRect * @param {object} hovered contains booleans at which position the * `hoveredRect` is hovered. */ _adaptiveTilingPreviewGroup(window, hoveredRect, hovered) { // Find the smallest window that will be affected and use it to calculate // the sizes of the preview. Determine the new tileRects for the rest // of the tileGroup via Rect.minus(). const smallestWindow = this._topTileGroup.reduce((smallest, w) => { if (hovered.atTopEdge) { if (w.tiledRect.y === hoveredRect.y || w.tiledRect.y2 === hoveredRect.y) return w.tiledRect.height < smallest.tiledRect.height ? w : smallest; } else if (hovered.atBottomEdge) { if (w.tiledRect.y === hoveredRect.y2 || w.tiledRect.y2 === hoveredRect.y2) return w.tiledRect.height < smallest.tiledRect.height ? w : smallest; } else if (hovered.atLeftEdge) { if (w.tiledRect.x === hoveredRect.x || w.tiledRect.x2 === hoveredRect.x) return w.tiledRect.width < smallest.tiledRect.width ? w : smallest; } else if (hovered.atRightEdge) { if (w.tiledRect.x === hoveredRect.x2 || w.tiledRect.x2 === hoveredRect.x2) return w.tiledRect.width < smallest.tiledRect.width ? w : smallest; } return smallest; }); const monitor = global.display.get_current_monitor(); const workArea = new Rect(window.get_work_area_for_monitor(monitor)); // This factor is used in combination with the smallestWindow to // determine the final size of the grabbed window. Use half of the size // factor, if we are at the screen edges. The cases for the bottom and // right screen edges are covered further down. const factor = hovered.atLeftEdge && hoveredRect.x === workArea.x || hovered.atTopEdge && hoveredRect.y === workArea.y ? 1 / 3 : 2 / 3; // The grabbed window will be horizontal. The horizontal size (x1 - x2) // is determined by the furthest left- and right-reaching windows that // align with the hovered rect. The vertical size (height) is a fraction // of the smallestWindow. if (hovered.atTopEdge || hovered.atBottomEdge) { const getX1X2 = alignsAt => { return this._topTileGroup.reduce((x1x2, w) => { const currX = x1x2[0]; const currX2 = x1x2[1]; return alignsAt(w) ? [Math.min(w.tiledRect.x, currX), Math.max(w.tiledRect.x2, currX2)] : x1x2; }, [hoveredRect.x, hoveredRect.x2]); }; const alignTopEdge = w => { return hoveredRect.y === w.tiledRect.y || hoveredRect.y === w.tiledRect.y2; }; const alignBottomEdge = w => { return hoveredRect.y2 === w.tiledRect.y2 || hoveredRect.y2 === w.tiledRect.y; }; const [x1, x2] = getX1X2(hovered.atTopEdge ? alignTopEdge : alignBottomEdge); const size = Math.ceil(smallestWindow.tiledRect.height * factor); // Keep within workArea bounds. const y = Math.max(workArea.y, Math.floor(hovered.atTopEdge ? hoveredRect.y - size / 2 : hoveredRect.y2 - size / 2 )); const height = Math.min(size, workArea.y2 - y); this._tileRect = new Rect(x1, y, x2 - x1, height); // The grabbed window will be vertical. The vertical size (y1 - y2) is // determined by the furthest top- and bottom-reaching windows that align // with the hovered rect. The horizontal size (width) is a fraction of // the smallestWindow. } else { const getY1Y2 = alignsAt => { return this._topTileGroup.reduce((y1y2, w) => { const currY = y1y2[0]; const currY2 = y1y2[1]; return alignsAt(w) ? [Math.min(w.tiledRect.y, currY), Math.max(w.tiledRect.y2, currY2)] : y1y2; }, [hoveredRect.y, hoveredRect.y2]); }; const alignLeftEdge = w => { return hoveredRect.x === w.tiledRect.x || hoveredRect.x === w.tiledRect.x2; }; const alignRightEdge = w => { return hoveredRect.x2 === w.tiledRect.x2 || hoveredRect.x2 === w.tiledRect.x; }; const [y1, y2] = getY1Y2(hovered.atLeftEdge ? alignLeftEdge : alignRightEdge); const size = Math.ceil(smallestWindow.tiledRect.width * factor); // Keep within workArea bounds. const x = Math.max(workArea.x, Math.floor(hovered.atLeftEdge ? hoveredRect.x - size / 2 : hoveredRect.x2 - size / 2 )); const width = Math.min(size, workArea.x2 - x); this._tileRect = new Rect(x, y1, width, y2 - y1); } this._tileRect.tryAlignWith(workArea); if (!this._tilePreview.needsUpdate(this._tileRect)) return; this._tilePreview.open(window, this._tileRect.meta, monitor); this._splitRects.clear(); this._topTileGroup.forEach(w => { const leftOver = w.tiledRect.minus(this._tileRect); const splitRect = leftOver[0]; // w isn't an affected window. if (splitRect?.equal(this._tileRect) ?? true) return; this._splitRects.set(w, splitRect); }); } _favoriteLayoutTilingPreview(window) { // Holding Super will make the window span multiple rects of the favorite // layout starting from the rect, which the user starting holding Super in. const isSuperPressed = Util.isModPressed(Clutter.ModifierType.MOD4_MASK); for (const rect of this._favoriteLayout) { if (rect.containsPoint(this._lastPointerPos)) { if (isSuperPressed) { this._anchorRect = this._anchorRect ?? rect; this._tileRect = rect.union(this._anchorRect); } else { this._tileRect = rect.copy(); this._anchorRect = null; } this._tilePreview.open(window, this._tileRect.meta, this._monitorNr, { x: this._tileRect.x, y: this._tileRect.y, width: this._tileRect.width, height: this._tileRect.height, opacity: 200 }); return; } } this._tileRect = null; this._tilePreview.close(); } } const TilePreview = GObject.registerClass( class TilePreview extends WindowManager.TilePreview { _init() { super._init(); this.set_style_class_name('tile-preview'); } needsUpdate(rect) { return !this._rect || !rect.equal(this._rect); } // Added param for animation and removed style for rounded corners open(window, tileRect, monitorIndex, animateTo = undefined) { const windowActor = window.get_compositor_private(); if (!windowActor) return; global.window_group.set_child_below_sibling(this, windowActor); if (this._rect && this._rect.equal(tileRect)) return; const changeMonitor = this._monitorIndex === -1 || this._monitorIndex !== monitorIndex; this._monitorIndex = monitorIndex; this._rect = tileRect; const monitor = Main.layoutManager.monitors[monitorIndex]; if (!this._showing || changeMonitor) { const monitorRect = new Mtk.Rectangle({ x: monitor.x, y: monitor.y, width: monitor.width, height: monitor.height }); const [, rect] = window.get_frame_rect().intersect(monitorRect); this.set_size(rect.width, rect.height); this.set_position(rect.x, rect.y); this.opacity = 0; } this._showing = true; this.show(); if (!animateTo) { animateTo = { x: tileRect.x, y: tileRect.y, width: tileRect.width, height: tileRect.height, opacity: 255, duration: WINDOW_ANIMATION_TIME, mode: Clutter.AnimationMode.EASE_OUT_QUAD }; } else { animateTo.x === undefined && this.set_x(tileRect.x); animateTo.y === undefined && this.set_y(tileRect.y); animateTo.width === undefined && this.set_width(tileRect.width); animateTo.height === undefined && this.set_height(tileRect.height); animateTo.opacity === undefined && this.set_opacity(255); animateTo.duration = animateTo.duration ?? WINDOW_ANIMATION_TIME; animateTo.mode = animateTo.mode ?? Clutter.AnimationMode.EASE_OUT_QUAD; } this.ease(animateTo); } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/resizeHandler.js000066400000000000000000000564761457776040200311560ustar00rootroot00000000000000import { Clutter, Meta } from '../dependencies/gi.js'; import { Orientation, Settings } from '../common.js'; import { Rect, Util } from './utility.js'; import { TilingWindowManager as Twm } from './tilingWindowManager.js'; const Side = { NONE: 0, SAME_H: 1, OPPOSING_H: 2, SAME_V: 4, OPPOSING_V: 8 }; /** * This class gets to handle the resize events of windows (whether they are * tiled or not). If a window isn't tiled, nothing happens. If the resized * window is tiled, auto-resize the complementing tiled windows. Intercardinal * resizing is split into its [H]orizontal and [V]ertical components. */ export default class TilingResizeHandler { constructor() { const isResizing = grabOp => { switch (grabOp) { case Meta.GrabOp.RESIZING_N: case Meta.GrabOp.RESIZING_NW: case Meta.GrabOp.RESIZING_NE: case Meta.GrabOp.RESIZING_S: case Meta.GrabOp.RESIZING_SW: case Meta.GrabOp.RESIZING_SE: case Meta.GrabOp.RESIZING_E: case Meta.GrabOp.RESIZING_W: return true; default: return false; } }; const g1 = global.display.connect('grab-op-begin', (d, window, grabOp) => { grabOp &= ~1024; // META_GRAB_OP_WINDOW_FLAG_UNCONSTRAINED if (window && isResizing(grabOp)) this._onResizeStarted(window, grabOp); }); const g2 = global.display.connect('grab-op-end', (d, window, grabOp) => { grabOp &= ~1024; // META_GRAB_OP_WINDOW_FLAG_UNCONSTRAINED if (window && isResizing(grabOp)) this._onResizeFinished(window, grabOp); }); this._displaySignals = []; this._displaySignals.push(g1); this._displaySignals.push(g2); this._sizeChangedId = 0; this._preGrabRects = new Map(); // Save the windows, which are to be resized (passively) along the // actively grabbed one, and a resizeOp. A resizeOp saves the side // of the window, which will be passively resized, relative to the // actively resized window. this._resizeOps = new Map(); } destroy() { this._displaySignals.forEach(sId => global.display.disconnect(sId)); } _onResizeStarted(window, grabOp) { if (!window.isTiled) return; // Use the same margin for the alignment and equality check below. const margin = 5; let topTileGroup = Twm.getTopTileGroup(); topTileGroup.forEach(w => { this._preGrabRects.set(w, new Rect(w.get_frame_rect())); if (w !== window) // There is no snapping for tiled windows, if the user set a window // gap. So the windows may not align properly, if the user tried // to manually resize them to be edge to edge. In that case, assume // that windows that are within a certain margin distance to each // other are meant to align and resize them together. w.tiledRect.tryAlignWith(window.tiledRect, margin); }); // Windows can be part of multiple tile groups. We however only resize // the top most visible tile group. That means a tile group in a lower // stack position may share windows with the top tile group and after // the resize op those windows will no longer match with the lower tile // group's tiles. So remove the shared windows from the lower tile group. const allWindows = Twm.getWindows(); allWindows.forEach(w => { if (!w.isTiled) return; if (topTileGroup.includes(w)) return; // Gets a tile group of windows without the ones // which are about to be resized const group = Twm.getTileGroupFor(w); const newGroup = group.reduce((gr, win) => { !topTileGroup.includes(win) && gr.push(win); return gr; }, []); // Tile groups are the same if (group.length === newGroup.length) return; // Remove old tile group and create new one Twm.clearTilingProps(w.get_id()); Twm.updateTileGroup(newGroup); }); // Remove the actively resizing window to get the windows, which will // be passively resized. topTileGroup.splice(topTileGroup.indexOf(window), 1); const grabbedRect = window.tiledRect; // Holding Ctrl allows resizing windows which only directly (or transitively) // border the window being actively resized (instead of the entire tileGroup) const isCtrlPressed = Util.isModPressed(Clutter.ModifierType.CONTROL_MASK); const singleEdgeResizeOp = [ Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_S, Meta.GrabOp.RESIZING_W, Meta.GrabOp.RESIZING_E ]; if (isCtrlPressed && singleEdgeResizeOp.includes(grabOp)) topTileGroup = this._getWindowsForIndividualResize(window, topTileGroup, grabOp); switch (grabOp) { // Resizing cardinal directions case Meta.GrabOp.RESIZING_N: for (const otherWindow of topTileGroup) { const otherRect = otherWindow.tiledRect; const resizeOp = ResizeOp.createResizeOp( Util.equal(grabbedRect.y, otherRect.y, margin), Util.equal(grabbedRect.y, otherRect.y2, margin), false, false ); resizeOp && this._resizeOps.set(otherWindow, resizeOp); } this._sizeChangedId = window.connect('size-changed', this._onResizing.bind(this, window, grabOp, null)); break; case Meta.GrabOp.RESIZING_S: for (const otherWindow of topTileGroup) { const otherRect = otherWindow.tiledRect; const resizeOp = ResizeOp.createResizeOp( Util.equal(grabbedRect.y2, otherRect.y2, margin), Util.equal(grabbedRect.y2, otherRect.y, margin), false, false ); resizeOp && this._resizeOps.set(otherWindow, resizeOp); } this._sizeChangedId = window.connect('size-changed', this._onResizing.bind(this, window, grabOp, null)); break; case Meta.GrabOp.RESIZING_E: for (const otherWindow of topTileGroup) { const otherRect = otherWindow.tiledRect; const resizeOp = ResizeOp.createResizeOp( false, false, Util.equal(grabbedRect.x2, otherRect.x2, margin), Util.equal(grabbedRect.x2, otherRect.x, margin) ); resizeOp && this._resizeOps.set(otherWindow, resizeOp); } this._sizeChangedId = window.connect('size-changed', this._onResizing.bind(this, window, null, grabOp)); break; case Meta.GrabOp.RESIZING_W: for (const otherWindow of topTileGroup) { const otherRect = otherWindow.tiledRect; const resizeOp = ResizeOp.createResizeOp( false, false, Util.equal(grabbedRect.x, otherRect.x, margin), Util.equal(grabbedRect.x, otherRect.x2, margin) ); resizeOp && this._resizeOps.set(otherWindow, resizeOp); } this._sizeChangedId = window.connect('size-changed', this._onResizing.bind(this, window, null, grabOp)); break; // Resizing intercardinal directions: case Meta.GrabOp.RESIZING_NW: for (const otherWindow of topTileGroup) { const otherRect = otherWindow.tiledRect; const resizeOp = ResizeOp.createResizeOp( Util.equal(grabbedRect.y, otherRect.y, margin), Util.equal(grabbedRect.y, otherRect.y2, margin), Util.equal(grabbedRect.x, otherRect.x, margin), Util.equal(grabbedRect.x, otherRect.x2, margin) ); resizeOp && this._resizeOps.set(otherWindow, resizeOp); } this._sizeChangedId = window.connect('size-changed', this._onResizing.bind(this, window, Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_W)); break; case Meta.GrabOp.RESIZING_NE: for (const otherWindow of topTileGroup) { const otherRect = otherWindow.tiledRect; const resizeOp = ResizeOp.createResizeOp( Util.equal(grabbedRect.y, otherRect.y, margin), Util.equal(grabbedRect.y, otherRect.y2, margin), Util.equal(grabbedRect.x2, otherRect.x2, margin), Util.equal(grabbedRect.x2, otherRect.x, margin) ); resizeOp && this._resizeOps.set(otherWindow, resizeOp); } this._sizeChangedId = window.connect('size-changed', this._onResizing.bind(this, window, Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_E)); break; case Meta.GrabOp.RESIZING_SW: for (const otherWindow of topTileGroup) { const otherRect = otherWindow.tiledRect; const resizeOp = ResizeOp.createResizeOp( Util.equal(grabbedRect.y2, otherRect.y2, margin), Util.equal(grabbedRect.y2, otherRect.y, margin), Util.equal(grabbedRect.x, otherRect.x, margin), Util.equal(grabbedRect.x, otherRect.x2, margin) ); resizeOp && this._resizeOps.set(otherWindow, resizeOp); } this._sizeChangedId = window.connect('size-changed', this._onResizing.bind(this, window, Meta.GrabOp.RESIZING_S, Meta.GrabOp.RESIZING_W)); break; case Meta.GrabOp.RESIZING_SE: for (const otherWindow of topTileGroup) { const otherRect = otherWindow.tiledRect; const resizeOp = ResizeOp.createResizeOp( Util.equal(grabbedRect.y2, otherRect.y2, margin), Util.equal(grabbedRect.y2, otherRect.y, margin), Util.equal(grabbedRect.x2, otherRect.x2, margin), Util.equal(grabbedRect.x2, otherRect.x, margin) ); resizeOp && this._resizeOps.set(otherWindow, resizeOp); } this._sizeChangedId = window.connect('size-changed', this._onResizing.bind(this, window, Meta.GrabOp.RESIZING_S, Meta.GrabOp.RESIZING_E)); } } // Update the windows' tiledRects _onResizeFinished(window, grabOp) { if (this._sizeChangedId) { window.disconnect(this._sizeChangedId); this._sizeChangedId = 0; } if (!window.isTiled) return; const monitor = window.get_monitor(); const screenTopGap = Util.useIndividualGaps(monitor) ? Util.getScaledGap(Settings.SCREEN_TOP_GAP, monitor) : Util.getScaledGap(Settings.SINGLE_SCREEN_GAP, monitor); const screenLeftGap = Util.useIndividualGaps(monitor) ? Util.getScaledGap(Settings.SCREEN_LEFT_GAP, monitor) : Util.getScaledGap(Settings.SINGLE_SCREEN_GAP, monitor); const windowGap = Util.getScaledGap(Settings.WINDOW_GAP, monitor); const workArea = window.get_work_area_for_monitor(monitor); // First calculate the new tiledRect for window: // The new x / y coord for the window's tiledRect can be calculated by // a simple difference because resizing on the E / S side won't change // x / y and resizing on the N or W side will translate into a 1:1 shift const grabbedsNewRect = new Rect(window.get_frame_rect()); const grabbedsOldRect = this._preGrabRects.get(window); const isResizingW = (grabOp & Meta.GrabOp.RESIZING_W) > 1; // Shift the tiledRect by the resize amount let newGrabbedTiledRectX = window.tiledRect.x + (grabbedsNewRect.x - grabbedsOldRect.x); // Switch the screenGap for a windowGap if (isResizingW && window.tiledRect.x === workArea.x) newGrabbedTiledRectX = newGrabbedTiledRectX + screenLeftGap - windowGap / 2; // Same as W but different orientation const isResizingN = (grabOp & Meta.GrabOp.RESIZING_N) > 1; let newGrabbedTiledRectY = window.tiledRect.y + (grabbedsNewRect.y - grabbedsOldRect.y); if (isResizingN && window.tiledRect.y === workArea.y) newGrabbedTiledRectY = newGrabbedTiledRectY + screenTopGap - windowGap / 2; // If resizing on the E side, you can simply rely on get_frame_rect's // new width else x2 should stick to where it was (manual calc due // special cases like gnome-terminal) const isResizingE = (grabOp & Meta.GrabOp.RESIZING_E) > 1; const newGrabbedTiledRectWidth = isResizingE ? grabbedsNewRect.width + windowGap / 2 + (workArea.x === newGrabbedTiledRectX ? screenLeftGap : windowGap / 2) : window.tiledRect.x2 - newGrabbedTiledRectX; // Same principal applies to the height and resizing on the S side const isResizingS = (grabOp & Meta.GrabOp.RESIZING_S) > 1; const newGrabbedTiledRectHeight = isResizingS ? grabbedsNewRect.height + windowGap / 2 + (workArea.y === newGrabbedTiledRectY ? screenTopGap : windowGap / 2) : window.tiledRect.y2 - newGrabbedTiledRectY; const grabbedsOldTiledRect = window.tiledRect; window.tiledRect = new Rect( newGrabbedTiledRectX, newGrabbedTiledRectY, newGrabbedTiledRectWidth, newGrabbedTiledRectHeight ); // Now calculate the new tiledRects for the windows, which were resized // along the window based on the diff of the window's tiledRect pre // and after the grab. const tiledRectDiffX = window.tiledRect.x - grabbedsOldTiledRect.x; const tiledRectDiffY = window.tiledRect.y - grabbedsOldTiledRect.y; const tiledRectDiffWidth = window.tiledRect.width - grabbedsOldTiledRect.width; const tiledRectDiffHeight = window.tiledRect.height - grabbedsOldTiledRect.height; this._resizeOps.forEach((resizeOp, win) => { if (win === window) return; if (resizeOp.side & Side.SAME_H) { win.tiledRect.x += tiledRectDiffX; win.tiledRect.width += tiledRectDiffWidth; } else if (resizeOp.side & Side.OPPOSING_H) { win.tiledRect.x += isResizingE ? tiledRectDiffWidth : 0; win.tiledRect.width -= tiledRectDiffWidth; } if (resizeOp.side & Side.SAME_V) { win.tiledRect.y += tiledRectDiffY; win.tiledRect.height += tiledRectDiffHeight; } else if (resizeOp.side & Side.OPPOSING_V) { win.tiledRect.y += isResizingS ? tiledRectDiffHeight : 0; win.tiledRect.height -= tiledRectDiffHeight; } }); this._preGrabRects.clear(); this._resizeOps.clear(); } _onResizing(resizedWindow, grabOpV, grabOpH) { this._resizeOps.forEach((resizeOp, window) => { const rectV = this._getPassiveResizedRect(grabOpV, resizedWindow, window, resizeOp.side & Side.SAME_V, resizeOp.side & Side.OPPOSING_V); const rectH = this._getPassiveResizedRect(grabOpH, resizedWindow, window, resizeOp.side & Side.SAME_H, resizeOp.side & Side.OPPOSING_H); if (rectV && rectH) window.move_resize_frame(false, rectH[0], rectV[1], rectH[2], rectV[3]); else if (rectV) window.move_resize_frame(false, ...rectV); else if (rectH) window.move_resize_frame(false, ...rectH); }); } // Gets the rect for the non-grabbed window adapted to the resized // grabbed window *but* only adapted for 1 side (either vertically // or horizontally) at a time based on grabOp _getPassiveResizedRect(grabOp, resizedWindow, window, resizeOnSameSide, resizeOnOpposingSide) { if (!grabOp) return null; if (!resizeOnSameSide && !resizeOnOpposingSide) return null; const resizedRect = new Rect(resizedWindow.get_frame_rect()); const wRect = new Rect(window.get_frame_rect()); const preGrabRect = this._preGrabRects.get(window); const windowGap = Util.getScaledGap(Settings.WINDOW_GAP, window.get_monitor()); switch (grabOp) { case Meta.GrabOp.RESIZING_N: return resizeOnSameSide ? [wRect.x, resizedRect.y, wRect.width, preGrabRect.y2 - resizedRect.y] : [wRect.x, wRect.y, wRect.width, resizedRect.y - wRect.y - windowGap]; case Meta.GrabOp.RESIZING_S: return resizeOnSameSide ? [wRect.x, wRect.y, wRect.width, resizedRect.y2 - preGrabRect.y] : [wRect.x, resizedRect.y2 + windowGap, wRect.width, preGrabRect.y2 - resizedRect.y2 - windowGap]; case Meta.GrabOp.RESIZING_W: return resizeOnSameSide ? [resizedRect.x, wRect.y, preGrabRect.x2 - resizedRect.x, wRect.height] : [wRect.x, wRect.y, resizedRect.x - wRect.x - windowGap, wRect.height]; case Meta.GrabOp.RESIZING_E: return resizeOnSameSide ? [wRect.x, wRect.y, resizedRect.x2 - preGrabRect.x, wRect.height] : [resizedRect.x2 + windowGap, wRect.y, preGrabRect.x2 - resizedRect.x2 - windowGap, wRect.height]; } } /** * Gets the windows which should be resized for the 'individual' resize mode. * That means all windows that directly (or transitively) border the window * being resized at the resized edge. * * @param {Meta.Window} window the window that is actively resized. * @param {Meta.Window[]} tileGroup the top tile group. * @param {Meta.GrabOp} grabOp * @returns {Meta.Window[]} all windows that will resize using the individual resize mode */ _getWindowsForIndividualResize(window, tileGroup, grabOp) { // Resizes on the same side as the one being resized by the user. // Starts with the window that is actively being resized by the user. const sameSide = [window]; // Resizes on the opposite side as the one being resized by the user const oppositeSide = []; const resizeIsNOrW = [Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_W].includes(grabOp); const orientation = [Meta.GrabOp.RESIZING_N, Meta.GrabOp.RESIZING_S].includes(grabOp) ? Orientation.V : Orientation.H; // Checks if the w1 and w2 border each other at a certain edge. const borders = (w1, w2, w1IsAfterW2) => { const [start, end] = orientation === Orientation.H ? ['x', 'x2'] : ['y', 'y2']; const overlap = orientation === Orientation.H ? 'vertOverlap' : 'horizOverlap'; if (w1IsAfterW2) { return w1.tiledRect[start] === w2.tiledRect[end] && w1.tiledRect[overlap](w2.tiledRect); } else { return w1.tiledRect[end] === w2.tiledRect[start] && w1.tiledRect[overlap](w2.tiledRect); } }; /** * @param {Meta.Window[]} uncheckedWindows windows yet to be checked. * @param {Meta.Window[]} checkingWindows windows, which the bordering windows * are searched for. It initially only starts with the window that is * actively resized by the user. * @param {Meta.Window[]} borderingWindows the windows that border the * checkingWindows on the resized edge. * @param {boolean} sideDeterminant determines which edge the * bordering is checked on. It's the relation of the checkingWindows * to the actively resized windows. */ const findBorderingWindows = (uncheckedWindows, checkingWindows, borderingWindows, sideDeterminant) => { const oldCount = borderingWindows.length; checkingWindows.forEach(w => { uncheckedWindows.forEach(unchecked => { if (borders(w, unchecked, sideDeterminant)) borderingWindows.push(unchecked); }); }); if (oldCount !== borderingWindows.length) { // Find the bordering windows for the newly added windows by // flipping the checkingWindows and borderingWindows arrays as well as // the side that is checked with the borders function. findBorderingWindows( uncheckedWindows.filter(w => !borderingWindows.includes(w)), borderingWindows, checkingWindows, !sideDeterminant ); } }; findBorderingWindows(tileGroup, sameSide, oppositeSide, resizeIsNOrW); return [...sameSide, ...oppositeSide]; } } /** * Saves information on which side a window will resize to complement the * grabbed window. A non-grabbed window can resize on the 'same side', on * the 'opposing side' or not at all. For ex.: Resizing the top-left quarter * on the E side means the bottom-left quarter resizes on the same side (E) * and the top / bottom-right quarters resize on the opposing side (W). If * the bottom window wasn't quartered but instead had its width equal the * workArea.width, then it wouldn't resize at all. */ const ResizeOp = class ResizeOp { /** * @param {number} side */ constructor(side) { this.side = side; } /** * @param {boolean} resizeOnSameSideV * @param {boolean} resizeOnOpposingSideV * @param {boolean} resizeOnSameSideH * @param {boolean} resizeOnOpposingSideH * @returns {ResizeOp|null} */ static createResizeOp(resizeOnSameSideV, resizeOnOpposingSideV, resizeOnSameSideH, resizeOnOpposingSideH) { let verticalResizeSide = Side.NONE; let horizontalResizeSide = Side.NONE; if (resizeOnSameSideV) verticalResizeSide = Side.SAME_V; else if (resizeOnOpposingSideV) verticalResizeSide = Side.OPPOSING_V; if (resizeOnSameSideH) horizontalResizeSide = Side.SAME_H; else if (resizeOnOpposingSideH) horizontalResizeSide = Side.OPPOSING_H; const resizeSide = verticalResizeSide | horizontalResizeSide; return resizeSide ? new ResizeOp(resizeSide) : null; } }; Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js000066400000000000000000000654451457776040200314210ustar00rootroot00000000000000import { Clutter, GObject, Meta, St } from '../dependencies/gi.js'; import { _, Main } from '../dependencies/shell.js'; import { Direction, Orientation, Settings } from '../common.js'; import { Rect, Util } from './utility.js'; import { TilingWindowManager as Twm } from './tilingWindowManager.js'; const SCALE_SIZE = 100; const Modes = { DEFAULT: 1, SWAP: 2, RESIZE: 4, MOVE: 8, CLOSE: 16 }; /** * Classes for the 'Tile Editing Mode'. A mode to manage your tiled windows * with your keyboard (and only the keyboard). The Tile Editor gets instanced * as soon as the keyboard shortcut is activated. The Handler classes are * basically modes / states for the Tile Editor each with a 'on key press' and * 'on key released' function. */ export const TileEditor = GObject.registerClass( class TileEditingMode extends St.Widget { _init() { super._init({ reactive: true }); this._haveModal = false; // The windows managed by the Tile Editor, that means the tiled windows // that aren't overlapped by other windows; in other words: the top tile Group this._windows = []; // Indicate the active selection by the user. Added to `this`. this._selectIndicator = null; this._mode = Modes.DEFAULT; // Handler of keyboard events depending on the mode. this._keyHandler = null; Main.uiGroup.add_child(this); this.connect('key-press-event', (__, event) => this._onKeyPressEvent(event)); } open() { this._windows = Twm.getTopTileGroup(); const grab = Main.pushModal(this); // We expect at least a keyboard grab here if ((grab.get_seat_state() & Clutter.GrabState.KEYBOARD) === 0) { Main.popModal(grab); return false; } this._grab = grab; this._haveModal = true; const openWindows = Twm.getWindows(); if (!openWindows.length || !this._windows.length) { const msg = _("Can't enter 'Tile Editing Mode', if no tiled window is visible."); Main.notify('Tiling Assistant', msg); this.close(); return; } this.monitor = this._windows[0].get_monitor(); const display = global.display.get_monitor_geometry(this.monitor); this.set_position(display.x, display.y); this.set_size(display.width, display.height); // Enter initial state. this._mode = Modes.DEFAULT; this._keyHandler = new DefaultKeyHandler(this); // The windows may not be at the foreground. They just weren't // overlapping other windows. So raise the entire tile group. this._windows.forEach(w => { if (w.raise_and_make_recent_on_workspace) w.raise_and_make_recent_on_workspace(global.workspace_manager.get_active_workspace()); else w.raise_and_make_recent(); }); // Create the active selection indicator. const window = this._windows[0]; const params = { style_class: 'tile-preview' }; this._selectIndicator = new Indicator(window.tiledRect, this.monitor, params); this._selectIndicator.focus(window.tiledRect, window); this.add_child(this._selectIndicator); } close() { if (this._haveModal) { Main.popModal(this._grab); this._haveModal = false; } this._windows = []; this._keyHandler = null; // this._selectIndicator may be undefined, if Tile Editing Mode is // left as soon as it's entered (e. g. when there's no tile group). this._selectIndicator?.window?.activate(global.get_current_time()); this._selectIndicator?.ease({ x: this._selectIndicator.x + SCALE_SIZE / 2, y: this._selectIndicator.y + SCALE_SIZE / 2, width: this._selectIndicator.width - SCALE_SIZE, height: this._selectIndicator.height - SCALE_SIZE, opacity: 0, duration: 150, mode: Clutter.AnimationMode.EASE_OUT_QUAD, onComplete: () => this.destroy() }) ?? this.destroy(); } vfunc_button_press_event() { this._keyHandler.prepareLeave(); this.close(); } async _onKeyPressEvent(keyEvent) { const mods = keyEvent.get_state(); let newMode; // Swap windows if (mods & Clutter.ModifierType.CONTROL_MASK) newMode = Modes.SWAP; // Move group to different workspace / monitor else if (mods & Clutter.ModifierType.SHIFT_MASK) newMode = Modes.MOVE; // Resize windows else if (mods & Clutter.ModifierType.MOD4_MASK) newMode = Modes.RESIZE; // Default keys else newMode = Modes.DEFAULT; // First switch mode, if a new mod is pressed. if (newMode !== this._mode) this._switchMode(newMode); // Handle the key press and get mode depending on that. newMode = await this._keyHandler.handleKeyPress(keyEvent); if (newMode && newMode !== this._mode) this._switchMode(newMode); } vfunc_key_release_event(keyEvent) { const newMode = this._keyHandler.handleKeyRelease(keyEvent); if (newMode && newMode !== this._mode) this._switchMode(newMode); } _switchMode(newMode) { if (!newMode) return; this._mode = newMode; this._keyHandler.prepareLeave(); switch (newMode) { case Modes.DEFAULT: this._keyHandler = new DefaultKeyHandler(this); break; case Modes.SWAP: this._keyHandler = new SwapKeyHandler(this); break; case Modes.MOVE: this._keyHandler = new MoveKeyHandler(this); break; case Modes.RESIZE: this._keyHandler = new ResizeKeyHandler(this); break; case Modes.CLOSE: this.close(); } } }); /** * Indicate the user selection or other stuff. */ const Indicator = GObject.registerClass(class TileEditingModeIndicator extends St.Widget { /** * @param {string} widgetParams * @param {Rect} rect the final rect / pos of the indicator * @param {number} monitor */ _init(rect, monitor, widgetParams = {}) { // Start from a scaled down position. super._init({ ...widgetParams, x: rect.x + SCALE_SIZE / 2, y: rect.y + SCALE_SIZE / 2, width: rect.width - SCALE_SIZE, height: rect.height - SCALE_SIZE, opacity: 0 }); this.rect = null; this.window = null; this._monitor = monitor; } /** * Animate the indicator to a specific position. * * @param {Rect} rect the position the indicator will animate to. * @param {Meta.Window|null} window the window at `rect`'s position. */ focus(rect, window = null) { const display = global.display.get_monitor_geometry(this._monitor); const activeWs = global.workspace_manager.get_active_workspace(); const workArea = new Rect(activeWs.get_work_area_for_monitor(this._monitor)); // Adjusted for window / screen gaps const { x, y, width, height } = rect.addGaps(workArea); this.ease({ x: x - display.x, y: y - display.y, width, height, opacity: 255, duration: 150, mode: Clutter.AnimationMode.EASE_OUT_QUAD }); this.rect = rect; this.window = window; } }); /** * Base class for other keyboard handlers and the default handler itself. * * @param {TileEditingMode} tileEditor */ const DefaultKeyHandler = class DefaultKeyHandler { constructor(tileEditor) { this._tileEditor = tileEditor; } /** * Automatically called when leaving a mode. */ prepareLeave() { } /** * Automatically called on a keyEvent. * * @param {number} keyEvent * @returns {Modes} The mode to enter after the event was handled. */ async handleKeyPress(keyEvent) { const keyVal = keyEvent.get_key_symbol(); // [Directions] to move focus with WASD, hjkl or arrow keys const dir = Util.getDirection(keyVal); if (dir) { this._focusInDir(dir); // [E]xpand to fill the available space } else if (keyVal === Clutter.KEY_e || keyVal === Clutter.KEY_E) { const window = this._selectIndicator.window; if (!window) return Modes.DEFAULT; const tiledRect = this._windows.map(w => w.tiledRect); const tileRect = Twm.getBestFreeRect(tiledRect, { currRect: window.tiledRect }); if (window.tiledRect.equal(tileRect)) return Modes.DEFAULT; const workArea = window.get_work_area_current_monitor(); const maximize = tileRect.equal(workArea); if (maximize && this._windows.length > 1) return Modes.DEFAULT; Twm.tile(window, tileRect, { openTilingPopup: false }); if (maximize) return Modes.CLOSE; this._selectIndicator.focus(window.tiledRect, window); // [C]ycle through halves of the available space around the window } else if (keyVal === Clutter.KEY_c || keyVal === Clutter.KEY_C) { const window = this._selectIndicator.window; if (!window) return Modes.DEFAULT; const tiledRects = this._windows.map(w => w.tiledRect); const fullRect = Twm.getBestFreeRect(tiledRects, { currRect: window.tiledRect }); const topHalf = fullRect.getUnitAt(0, fullRect.height / 2, Orientation.H); const rightHalf = fullRect.getUnitAt(1, fullRect.width / 2, Orientation.V); const bottomHalf = fullRect.getUnitAt(1, fullRect.height / 2, Orientation.H); const leftHalf = fullRect.getUnitAt(0, fullRect.width / 2, Orientation.V); const rects = [topHalf, rightHalf, bottomHalf, leftHalf]; const currIdx = rects.findIndex(r => r.equal(window.tiledRect)); const newIndex = (currIdx + 1) % 4; Twm.tile(window, rects[newIndex], { openTilingPopup: false }); this._selectIndicator.focus(window.tiledRect, window); // [Q]uit a window } else if (keyVal === Clutter.KEY_q || keyVal === Clutter.KEY_Q) { const window = this._selectIndicator.window; if (!window) return Modes.DEFAULT; this._windows.splice(this._windows.indexOf(window), 1); window.delete(global.get_current_time()); const newWindow = this._windows[0]; if (!newWindow) return Modes.CLOSE; this._selectIndicator.focus(newWindow.tiledRect, newWindow); // [R]estore a window's size } else if (keyVal === Clutter.KEY_r || keyVal === Clutter.KEY_R) { const window = this._selectIndicator.window; if (!window) return Modes.DEFAULT; const selectedRect = window.tiledRect.copy(); this._windows.splice(this._windows.indexOf(window), 1); Twm.untile(window); if (!this._windows.length) return Modes.CLOSE; // Re-raise tile group, so it isn't below the just-untiled window if (this._windows[0].raise_and_make_recent_on_workspace) this._windows[0].raise_and_make_recent_on_workspace(global.workspace_manager.get_active_workspace()); else this._windows[0].raise_and_make_recent(); this._selectIndicator.focus(selectedRect, null); // [Enter] / [Esc]ape Tile Editing Mode } else if (keyVal === Clutter.KEY_Escape || keyVal === Clutter.KEY_Return) { return Modes.CLOSE; // [Space] to activate the Tiling Popup } else if (keyVal === Clutter.KEY_space) { const allWs = Settings.getBoolean(Settings.POPUP_ALL_WORKSPACES); const openWindows = Twm.getWindows(allWs).filter(w => !this._windows.includes(w)); const TilingPopup = await import('./tilingPopup.js'); const tilingPopup = new TilingPopup.TilingSwitcherPopup( openWindows, this._selectIndicator.rect, false ); if (!tilingPopup.show(this._windows)) { tilingPopup.destroy(); return Modes.DEFAULT; } tilingPopup.connect('closed', (popup, canceled) => { if (canceled) return; const { tiledWindow } = popup; const replaced = this._windows.findIndex(w => w.tiledRect.equal(tiledWindow.tiledRect)); replaced !== -1 && this._windows.splice(replaced, 1); // Create the new tile group to allow 1 window to be part of multiple tile groups Twm.updateTileGroup([tiledWindow, ...this._windows]); this._windows.unshift(tiledWindow); this._selectIndicator.focus(tiledWindow.tiledRect, tiledWindow); }); } return Modes.DEFAULT; } /** * Automatically called on a keyEvent. * * @param {number} keyEvent * @returns {Modes|undefined} The mode to enter after the event was handled. */ handleKeyRelease() { return undefined; } /** * Move the the selection indicator towards direction of `dir`. * * @param {Direction} dir */ _focusInDir(dir) { const activeWs = global.workspace_manager.get_active_workspace(); const workArea = new Rect(activeWs.get_work_area_for_monitor(this._tileEditor.monitor)); const tiledRects = this._windows.map(w => w.tiledRect); const screenRects = tiledRects.concat(workArea.minus(tiledRects)); const nearestRect = this._selectIndicator.rect.getNeighbor(dir, screenRects); if (!nearestRect) return; const newWindow = this._windows.find(w => w.tiledRect.equal(nearestRect)); this._selectIndicator.focus(newWindow?.tiledRect ?? nearestRect, newWindow); } get _windows() { return this._tileEditor._windows; } get _selectIndicator() { return this._tileEditor._selectIndicator; } }; /** * Move the selected window to a different position. If there is a window at * the new position, the 2 windows will swap their positions. * * @param {TileEditingMode} tileEditor */ const SwapKeyHandler = class SwapKeyHandler extends DefaultKeyHandler { constructor(tileEditor) { super(tileEditor); // Create an 'anchor indicator' to indicate the window that will be swapped const color = this._selectIndicator.get_theme_node().get_background_color(); const { red, green, blue, alpha } = color; this._anchorIndicator = new Indicator(this._selectIndicator.rect, tileEditor.monitor, { style: `background-color: rgba(${red}, ${green}, ${blue}, ${alpha / 255})` }); this._anchorIndicator.focus(this._selectIndicator.rect, this._selectIndicator.window); this._tileEditor.add_child(this._anchorIndicator); } prepareLeave() { this._anchorIndicator.destroy(); } handleKeyPress(keyEvent) { const direction = Util.getDirection(keyEvent.get_key_symbol()); // [Directions] to choose a window to swap with WASD, hjkl or arrow keys if (direction) this._focusInDir(direction); // [Esc]ape Tile Editing Mode else if (keyEvent.get_key_symbol() === Clutter.KEY_Escape) return Modes.DEFAULT; return Modes.SWAP; } handleKeyRelease(keyEvent) { const keyVal = keyEvent.get_key_symbol(); const ctrlKeys = [Clutter.KEY_Control_L, Clutter.KEY_Control_R]; if (ctrlKeys.includes(keyVal)) { this._swap(); return Modes.DEFAULT; } return Modes.SWAP; } _swap() { if (this._anchorIndicator.window) { Twm.tile(this._anchorIndicator.window, this._selectIndicator.rect, { openTilingPopup: false }); } if (this._selectIndicator.window) { Twm.tile(this._selectIndicator.window, this._anchorIndicator.rect, { openTilingPopup: false }); } this._selectIndicator.focus(this._selectIndicator.rect, this._anchorIndicator.window); } }; /** * Move the tile group to a different workspace / monitor. * * @param {TileEditingMode} tileEditor */ const MoveKeyHandler = class MoveKeyHandler extends DefaultKeyHandler { handleKeyPress(keyEvent) { const direction = Util.getDirection(keyEvent.get_key_symbol()); const moveWorkspace = keyEvent.get_state() & Clutter.ModifierType.MOD1_MASK; // [Directions] to move the tile group if (direction) { // To new workspace if (moveWorkspace) { let metaDir = Meta.MotionDirection.UP; if (direction === Direction.N) metaDir = Meta.MotionDirection.UP; else if (direction === Direction.S) metaDir = Meta.MotionDirection.DOWN; else if (direction === Direction.W) metaDir = Meta.MotionDirection.LEFT; else if (direction === Direction.E) metaDir = Meta.MotionDirection.RIGHT; const activeWs = global.workspace_manager.get_active_workspace(); const newWs = activeWs.get_neighbor(metaDir); if (activeWs === newWs) return Modes.MOVE; Twm.moveGroupToWorkspace(this._tileEditor._windows, newWs); // To new monitor } else { let metaDir = Meta.DisplayDirection.UP; if (direction === Direction.N) metaDir = Meta.DisplayDirection.UP; else if (direction === Direction.S) metaDir = Meta.DisplayDirection.DOWN; else if (direction === Direction.W) metaDir = Meta.DisplayDirection.LEFT; else if (direction === Direction.E) metaDir = Meta.DisplayDirection.RIGHT; // get_current_monitor isn't accurate for our case const currMonitor = this._tileEditor.monitor; const newMonitor = global.display.get_monitor_neighbor_index(currMonitor, metaDir); if (newMonitor === -1) return Modes.MOVE; Twm.moveGroupToMonitor(this._tileEditor._windows, currMonitor, newMonitor); } return Modes.CLOSE; // [Esc] to return to default mode } else if (keyEvent.get_key_symbol() === Clutter.KEY_Escape) { return Modes.DEFAULT; } return Modes.MOVE; } }; /** * Handler to resize the highlighted window. * * @param {TileEditor} tileEditor */ const ResizeKeyHandler = class ResizeKeyHandler extends DefaultKeyHandler { constructor(tileEditor) { super(tileEditor); // The edge that is currently being resized. this._currEdge = null; this._resizeSideIndicator = null; } prepareLeave() { this._resizeSideIndicator?.destroy(); } handleKeyPress(keyEvent) { // [Directions] to resize with WASD, hjkl or arrow keys const direction = Util.getDirection(keyEvent.get_key_symbol()); if (direction) { const window = this._selectIndicator.window; if (!window) return Modes.DEFAULT; // First call: Go to an edge. if (!this._currEdge) { this._currEdge = direction; this._createResizeIndicator(); return Modes.RESIZE; // Change resize orientation from H to V } else if ([Direction.N, Direction.S].includes(this._currEdge)) { if ([Direction.W, Direction.E].includes(direction)) { this._currEdge = direction; this._createResizeIndicator(); return Modes.RESIZE; } // Change resize orientation from V to H } else if ([Direction.W, Direction.E].includes(this._currEdge)) { if ([Direction.N, Direction.S].includes(direction)) { this._currEdge = direction; this._createResizeIndicator(); return Modes.RESIZE; } } this._resize(window, direction); // Update the selection indicator. this._selectIndicator.focus(window.tiledRect, window); // Update resize side indicator this._resizeSideIndicator.updatePos(window.tiledRect); // [Esc]ape Tile Editing Mode } else if (keyEvent.get_key_symbol() === Clutter.KEY_Escape) { return Modes.CLOSE; } return Modes.RESIZE; } handleKeyRelease(keyEvent) { const keyVal = keyEvent.get_key_symbol(); const superKeys = [Clutter.KEY_Super_L, Clutter.KEY_Super_R]; return superKeys.includes(keyVal) ? Modes.DEFAULT : Modes.RESIZE; } _resize(window, keyDir) { // Rect, which is being resized by the user. But it still has // its original / pre-resize dimensions const resizedRect = window.tiledRect; const workArea = new Rect(window.get_work_area_current_monitor()); let resizeAmount = 50; // Limit resizeAmount to the workArea if (this._currEdge === Direction.N && keyDir === Direction.N) resizeAmount = Math.min(resizeAmount, resizedRect.y - workArea.y); else if (this._currEdge === Direction.S && keyDir === Direction.S) resizeAmount = Math.min(resizeAmount, workArea.y2 - resizedRect.y2); else if (this._currEdge === Direction.W && keyDir === Direction.W) resizeAmount = Math.min(resizeAmount, resizedRect.x - workArea.x); else if (this._currEdge === Direction.E && keyDir === Direction.E) resizeAmount = Math.min(resizeAmount, workArea.x2 - resizedRect.x2); if (resizeAmount <= 0) return; // Function to update the passed rect by the resizeAmount depending on // the edge that is resized. Some windows will resize on the same edge // as the one the user is resizing. Other windows will resize on the // opposite edge. const updateRectSize = (rect, resizeOnEdge) => { const growDir = keyDir === resizeOnEdge ? 1 : -1; switch (resizeOnEdge) { case Direction.N: rect.y -= resizeAmount * growDir; // falls through case Direction.S: rect.height += resizeAmount * growDir; break; case Direction.W: rect.x -= resizeAmount * growDir; // falls through case Direction.E: rect.width += resizeAmount * growDir; } }; // Actually resize the windows here. this._windows.forEach(w => { // The window, which is resized by the user, is included in this. if (this._isSameSide(resizedRect, w.tiledRect)) { const newRect = w.tiledRect.copy(); updateRectSize(newRect, this._currEdge); Twm.tile(w, newRect, { openTilingPopup: false }); } else if (this._isOppositeSide(resizedRect, w.tiledRect)) { const newRect = w.tiledRect.copy(); updateRectSize(newRect, Direction.opposite(this._currEdge)); Twm.tile(w, newRect, { openTilingPopup: false }); } }); } _isOppositeSide(rect1, rect2) { switch (this._currEdge) { case Direction.N: return rect1.y === rect2.y2; case Direction.S: return rect1.y2 === rect2.y; case Direction.W: return rect1.x === rect2.x2; case Direction.E: return rect1.x2 === rect2.x; } return false; } _isSameSide(rect1, rect2) { switch (this._currEdge) { case Direction.N: return rect1.y === rect2.y; case Direction.S: return rect1.y2 === rect2.y2; case Direction.W: return rect1.x === rect2.x; case Direction.E: return rect1.x2 === rect2.x2; } return false; } _createResizeIndicator() { this._resizeSideIndicator?.destroy(); this._resizeSideIndicator = new ResizeSideIndicator( this._currEdge, this._selectIndicator.rect); Main.uiGroup.add_child(this._resizeSideIndicator); } }; const ResizeSideIndicator = GObject.registerClass( class ResizeSideIndicator extends St.Widget { _init(edge, activeRect) { const [width, height] = [Direction.N, Direction.S].includes(edge) ? [200, 20] : [20, 200]; super._init({ width, height, opacity: 0, style: 'background-color: black;\ border-radius: 999px;' }); this._edge = edge; this._moveDist = 100; this.updatePos(activeRect); // Inner pill const innerWidth = this.width < this.height ? 4 : 75; const innerHeight = this.width < this.height ? 75 : 4; this.add_child(new St.Widget({ x: this.width / 2 - innerWidth / 2, y: this.height / 2 - innerHeight / 2, width: innerWidth, height: innerHeight, style: 'background-color: #ebebeb;\ border-radius: 999px;' })); } destroy() { this.ease({ opacity: 0, duration: 100, mode: Clutter.AnimationMode.EASE_OUT_QUAD, onComplete: () => super.destroy() }); } updatePos(rect) { let x, y; switch (this._edge) { case Direction.N: x = rect.center.x - this.width / 2; y = rect.y - this.height / 2; break; case Direction.S: x = rect.center.x - this.width / 2; y = rect.y2 - this.height / 2; break; case Direction.W: x = rect.x - this.width / 2; y = rect.center.y - this.height / 2; break; case Direction.E: x = rect.x2 - this.width / 2; y = rect.center.y - this.height / 2; } this.ease({ x, y, opacity: 255, duration: 150, mode: Clutter.AnimationMode.EASE_OUT_QUAD }); } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/tilingPopup.js000066400000000000000000000331231457776040200306510ustar00rootroot00000000000000import { Clutter, GObject, Meta, St } from '../dependencies/gi.js'; import { Main, SwitcherPopup } from '../dependencies/shell.js'; import { Direction, Orientation } from '../common.js'; import { Util } from './utility.js'; import { TilingWindowManager as Twm } from './tilingWindowManager.js'; import * as AltTab from './altTab.js'; /** * Classes for the Tiling Popup, which opens when tiling a window * and there is free screen space to fill with other windows. * Mostly based on GNOME's altTab.js */ export const TilingSwitcherPopup = GObject.registerClass({ Signals: { // Bool indicates whether the Tiling Popup was canceled // (or if a window was tiled with this popup) 'closed': { param_types: [GObject.TYPE_BOOLEAN] } } }, class TilingSwitcherPopup extends AltTab.TilingAppSwitcherPopup { /** * @param {Meta.Windows[]} openWindows an array of Meta.Windows, which this * popup offers to tile. * @param {Rect} freeScreenRect the Rect, which the popup will tile a window * to. The popup will be centered in this rect. * @param {boolean} allowConsecutivePopup allow the popup to create another * Tiling Popup, if there is still unambiguous free screen space after * this popup tiled a window. * @param {boolean} skipAnim */ _init(openWindows, freeScreenRect, allowConsecutivePopup = true, skipAnim = false) { this._freeScreenRect = freeScreenRect; this._shadeBG = null; this._monitor = -1; SwitcherPopup.SwitcherPopup.prototype._init.call(this); this._thumbnails = null; this._thumbnailTimeoutId = 0; this._currentWindow = -1; this.thumbnailsVisible = false; // The window, which was tiled with the Tiling Popup after it's closed // or null, if the popup was closed with tiling a window this.tiledWindow = null; this._allowConsecutivePopup = allowConsecutivePopup; this._skipAnim = skipAnim; this._switcherList = new TSwitcherList(this, openWindows); this._items = this._switcherList.icons; // Destroy popup when touching outside of popup this.connect('touch-event', () => { if (Meta.is_wayland_compositor()) this.fadeAndDestroy(); return Clutter.EVENT_PROPAGATE; }); } /** * @param {Array} tileGroup an array of Meta.Windows. When the popup * appears it will shade the background. These windows will won't * be affected by that. * @returns if the popup was successfully shown. */ show(tileGroup) { this._monitor = tileGroup[0]?.get_monitor() ?? global.display.get_current_monitor(); if (!this._items.length) return false; const grab = Main.pushModal(this); // We expect at least a keyboard grab here if ((grab.get_seat_state() & Clutter.GrabState.KEYBOARD) === 0) { Main.popModal(grab); return false; } this._grab = grab; this._haveModal = true; this._switcherList.connect('item-activated', this._itemActivated.bind(this)); this._switcherList.connect('item-entered', this._itemEntered.bind(this)); this._switcherList.connect('item-removed', this._itemRemoved.bind(this)); this.add_child(this._switcherList); // Need to force an allocation so we can figure out // whether we need to scroll when selecting this.visible = true; this.get_allocation_box(); this._select(0); Main.osdWindowManager.hideAll(); this._shadeBackground(tileGroup); this.opacity = 0; this.ease({ opacity: 255, duration: 200, mode: Clutter.AnimationMode.EASE_OUT_QUAD }); return true; } _shadeBackground(tileGroup) { const tiledWindow = tileGroup[0]; const activeWs = global.workspace_manager.get_active_workspace(); const workArea = activeWs.get_work_area_for_monitor(this._monitor); this._shadeBG = new St.Widget({ style: 'background-color : black', x: workArea.x, y: workArea.y, width: workArea.width, height: workArea.height, opacity: 0 }); global.window_group.add_child(this._shadeBG); this._shadeBG.ease({ opacity: 180, duration: 200, mode: Clutter.AnimationMode.EASE_OUT_QUAD }); if (!tiledWindow) return; // Clones to correctly shade the background for consecutive tiling. for (let i = 1; i < tileGroup.length; i++) { const wActor = tileGroup[i].get_compositor_private(); const clone = new Clutter.Clone({ source: wActor, x: wActor.x, y: wActor.y }); global.window_group.add_child(clone); wActor.hide(); this.connect('destroy', () => { wActor.show(); clone.destroy(); }); } const tActor = tiledWindow.get_compositor_private(); global.window_group.set_child_above_sibling(tActor, this._shadeBG); } vfunc_allocate(box) { this.set_allocation(box); const freeScreenRect = this._freeScreenRect; const childBox = new Clutter.ActorBox(); const leftPadding = this.get_theme_node().get_padding(St.Side.LEFT); const rightPadding = this.get_theme_node().get_padding(St.Side.RIGHT); const hPadding = leftPadding + rightPadding; const [, childNaturalHeight] = this._switcherList.get_preferred_height( freeScreenRect.width - hPadding); const [, childNaturalWidth] = this._switcherList.get_preferred_width(childNaturalHeight); childBox.x1 = Math.max(freeScreenRect.x + leftPadding, freeScreenRect.x + Math.floor((freeScreenRect.width - childNaturalWidth) / 2)); childBox.x2 = Math.min(freeScreenRect.x2 - rightPadding, childBox.x1 + childNaturalWidth); childBox.y1 = freeScreenRect.y + Math.floor((freeScreenRect.height - childNaturalHeight) / 2); childBox.y2 = childBox.y1 + childNaturalHeight; this._switcherList.allocate(childBox); if (this._thumbnails) { const cbox = this._switcherList.get_allocation_box(); const monitor = global.display.get_monitor_geometry(this._monitor); const leftPadd = this.get_theme_node().get_padding(St.Side.LEFT); const rightPadd = this.get_theme_node().get_padding(St.Side.RIGHT); const bottomPadding = this.get_theme_node().get_padding(St.Side.BOTTOM); const hPadd = leftPadd + rightPadd; const icon = this._items[this._selectedIndex]; const [posX] = icon.get_transformed_position(); const thumbnailCenter = posX + icon.width / 2; const [, cNatWidth] = this._thumbnails.get_preferred_width(-1); cbox.x1 = Math.max(monitor.x + leftPadd, Math.floor(thumbnailCenter - cNatWidth / 2) ); if (cbox.x1 + cNatWidth > monitor.x + monitor.width - hPadd) { const offset = cbox.x1 + cNatWidth - monitor.width + hPadd; cbox.x1 = Math.max(monitor.x + leftPadd, cbox.x1 - offset - hPadd); } const spacing = this.get_theme_node().get_length('spacing'); cbox.x2 = cbox.x1 + cNatWidth; if (cbox.x2 > monitor.x + monitor.width - rightPadd) cbox.x2 = monitor.x + monitor.width - rightPadd; cbox.y1 = this._switcherList.allocation.y2 + spacing; this._thumbnails.addClones(monitor.y + monitor.height - bottomPadding - cbox.y1); const [, cNatHeight] = this._thumbnails.get_preferred_height(-1); cbox.y2 = cbox.y1 + cNatHeight; this._thumbnails.allocate(cbox); } } vfunc_button_press_event(buttonEvent) { const btn = buttonEvent.get_button(); if (btn === Clutter.BUTTON_MIDDLE || btn === Clutter.BUTTON_SECONDARY) { this._finish(global.get_current_time()); return Clutter.EVENT_PROPAGATE; } return super.vfunc_button_press_event(buttonEvent); } _keyPressHandler(keysym) { const moveUp = Util.isDirection(keysym, Direction.N); const moveDown = Util.isDirection(keysym, Direction.S); const moveLeft = Util.isDirection(keysym, Direction.W); const moveRight = Util.isDirection(keysym, Direction.E); if (this._thumbnailsFocused) { if (moveLeft) this._select(this._selectedIndex, this._previousWindow()); else if (moveRight) this._select(this._selectedIndex, this._nextWindow()); else if (moveUp || moveDown) this._select(this._selectedIndex, null, true); else return Clutter.EVENT_PROPAGATE; } else if (moveLeft) { this._select(this._previous()); } else if (moveRight) { this._select(this._next()); } else if (moveDown || moveUp) { this._select(this._selectedIndex, 0); } else { return Clutter.EVENT_PROPAGATE; } return Clutter.EVENT_STOP; } _windowActivated(thumbnailSwitcher, n) { const window = this._items[this._selectedIndex].cachedWindows[n]; this._tileWindow(window); this.fadeAndDestroy(); } _finish(timestamp) { const appIcon = this._items[this._selectedIndex]; const window = appIcon.cachedWindows[Math.max(0, this._currentWindow)]; this._tileWindow(window); SwitcherPopup.SwitcherPopup.prototype._finish.call(this, timestamp); } fadeAndDestroy() { if (this._alreadyDestroyed) return; this._alreadyDestroyed = true; const canceled = !this.tiledWindow; this.emit('closed', canceled); this._shadeBG?.destroy(); this._shadeBG = null; super.fadeAndDestroy(); } _tileWindow(window) { let rect = this._freeScreenRect; // Halve the tile rect. // If isShiftPressed, then put the window at the top / left side; // if isAltPressed, then put it at the bottom / right side. // The orientation depends on the available screen space. const isShiftPressed = Util.isModPressed(Clutter.ModifierType.SHIFT_MASK); const isAltPressed = Util.isModPressed(Clutter.ModifierType.MOD1_MASK); if (isShiftPressed || isAltPressed) { // Prefer vertical a bit more (because screens are usually horizontal) const vertical = rect.width >= rect.height * 1.25; const size = vertical ? 'width' : 'height'; const orientation = vertical ? Orientation.V : Orientation.H; const idx = isShiftPressed ? 0 : 1; rect = rect.getUnitAt(idx, rect[size] / 2, orientation); } this.tiledWindow = window; window.change_workspace(global.workspace_manager.get_active_workspace()); // We want to activate/focus the window after it was tiled with the // Tiling Popup. Calling activate/focus() after tile() doesn't seem to // work for GNOME Terminal if it is maximized before trying to tile it. // It won't be tiled properly in that case for some reason... Instead // activate first but clear the tiling signals before so that the old // tile group won't be accidentally raised. Twm.clearTilingProps(window.get_id()); window.activate(global.get_current_time()); Twm.tile(window, rect, { monitorNr: this._monitor, openTilingPopup: this._allowConsecutivePopup, skipAnim: this._skipAnim }); } // Dont _finish(), if no mods are pressed _resetNoModsTimeout() { } }); const TSwitcherList = GObject.registerClass( class TilingSwitcherList extends AltTab.TilingAppSwitcher { _setIconSize() { let j = 0; while (this._items.length > 1 && this._items[j].style_class !== 'item-box') j++; const themeNode = this._items[j].get_theme_node(); this._list.ensure_style(); const iconPadding = themeNode.get_horizontal_padding(); const iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT); const [, labelNaturalHeight] = this.icons[j].label.get_preferred_height(-1); const iconSpacing = labelNaturalHeight + iconPadding + iconBorder; const totalSpacing = this._list.spacing * (this._items.length - 1); const freeScreenRect = this._altTabPopup._freeScreenRect; const parentPadding = this.get_parent().get_theme_node().get_horizontal_padding(); const availWidth = freeScreenRect.width - parentPadding - this.get_theme_node().get_horizontal_padding(); const scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; const baseIconSizes = [96, 64, 48, 32, 22]; const iconSizes = baseIconSizes.map(s => s * scaleFactor); let iconSize = baseIconSizes[0]; if (this._items.length > 1) { for (let i = 0; i < baseIconSizes.length; i++) { iconSize = baseIconSizes[i]; const height = iconSizes[i] + iconSpacing; const w = height * this._items.length + totalSpacing; if (w <= availWidth) break; } } this._iconSize = iconSize; for (let i = 0; i < this.icons.length; i++) this.icons[i].set_size(iconSize); } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/tilingWindowManager.js000066400000000000000000001655571457776040200323310ustar00rootroot00000000000000import { Clutter, GLib, GObject, Meta, Mtk, Shell } from '../dependencies/gi.js'; import { Main } from '../dependencies/shell.js'; import { getWindows } from '../dependencies/unexported/altTab.js'; import { Orientation, Settings, Shortcuts } from '../common.js'; import { Rect, Util } from './utility.js'; /** * Singleton responsible for tiling. Implement the signals in a separate Clutter * class so this doesn't need to be instanced. */ export class TilingWindowManager { static initialize() { this._signals = new TilingSignals(); // { windowId1: [windowIdX, windowIdY, ...], windowId2: [...], ... } this._tileGroups = new Map(); // [windowIds] this._unmanagingWindows = []; this._wsAddedId = global.workspace_manager.connect('workspace-added', this._onWorkspaceAdded.bind(this)); this._wsRemovedId = global.workspace_manager.connect('workspace-removed', this._onWorkspaceRemoved.bind(this)); } static destroy() { this._signals.destroy(); this._signals = null; global.workspace_manager.disconnect(this._wsAddedId); global.workspace_manager.disconnect(this._wsRemovedId); this._tileGroups.clear(); this._unmanagingWindows = []; if (this._openAppTiledTimerId) { GLib.Source.remove(this._openAppTiledTimerId); this._openAppTiledTimerId = null; } if (this._wsAddedTimer) { GLib.Source.remove(this._wsAddedTimer); this._wsAddedTimer = null; } if (this._wsRemovedTimer) { GLib.Source.remove(this._wsRemovedTimer); this._wsRemovedTimer = null; } } static connect(signal, func) { return this._signals.connect(signal, func); } static disconnect(id) { this._signals.disconnect(id); } static emit(...params) { this._signals.emit(...params); } /** * Gets windows, which can be tiled * * @param {boolean} [allWorkspaces=false] determines whether we only want * the windows from the current workspace. * @returns {Meta.Windows[]} an array of of the open Meta.Windows in * stacking order. */ static getWindows(allWorkspaces = false) { const activeWs = global.workspace_manager.get_active_workspace(); const openWindows = getWindows(allWorkspaces ? null : activeWs); // The open windows are not sorted properly when tiling with the Tiling // Popup because altTab sorts by focus. const sorted = global.display.sort_windows_by_stacking(openWindows); return sorted.reverse().filter(w => { // I don't think this should normally happen but if it does, this // extension can crash GNOME Shell.. so guard against it. A way to // have a window's monitor be -1, for example, is explained here: // https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4713 if (w.get_monitor() === -1) return false; // Assumption: a maximized window can also resize (once unmaximized) const canResize = w.allows_move() && w.allows_resize() || this.isMaximized(w); return canResize; }); } /** * @param {Meta.Window} window a Meta.Window. * @param {Meta.WorkArea|Rect|null} workArea useful for the grace period * @returns whether the window is maximized. Be it using GNOME's native * maximization or the maximization by this extension when using gaps. */ static isMaximized(window, workArea = null) { const area = workArea ?? window.get_work_area_current_monitor(); return window.get_maximized() === Meta.MaximizeFlags.BOTH || window.tiledRect?.equal(area); } /** * Tiles a window to a specific spot and setup all tiling properties. * * @param {Meta.Window} window a Meta.Window to tile. * @param {Rect} newRect the Rect the `window` will be tiled to. * @param {boolean} [openTilingPopup=true] decides, if we open a Tiling * Popup after the window is tiled and there is unambiguous free * screen space. * @param {number} [number=null] is used to get the workArea in which the * window tiles on. It's used for gap calculation. We can't always rely on * window.get_monitor with its monitor or global.display.get_current_monitor * (the pointer monitor) because of the 'grace period' during a quick dnd * towards a screen border since the pointer and the window will be on the * 'wrong' monitor. * @param {boolean} [skipAnim=false] decides, if we skip the tile animation. * @param {boolean} [tileGroup=null] forces the creation of this tile group. * @param {boolean} [fakeTile=false] don't create a new tile group, don't * emit 'tiled' signal or open the Tiling Popup */ static async tile(window, newRect, { openTilingPopup = true, ignoreTA = false, monitorNr = null, skipAnim = false, fakeTile = false } = {}) { if (!window || window.is_skip_taskbar()) return; const wasMaximized = window.get_maximized(); if (wasMaximized) window.unmaximize(wasMaximized); window.unmake_fullscreen(); if (!window.allows_resize() || !window.allows_move()) return; // Remove window from the other windows' tileGroups so it // doesn't falsely get raised with them. this.clearTilingProps(window.get_id()); window.unmake_above(); window.unminimize(); // Raise window since tiling with the popup means that // the window can be below others. if (window.raise_and_make_recent_on_workspace) window.raise_and_make_recent_on_workspace(global.workspace_manager.get_active_workspace()); else window.raise_and_make_recent(); const oldRect = new Rect(window.get_frame_rect()); const monitor = monitorNr ?? window.get_monitor(); const workArea = new Rect(window.get_work_area_for_monitor(monitor)); const maximize = newRect.equal(workArea); window.isTiled = !maximize; if (!window.untiledRect) window.untiledRect = oldRect; if (maximize && !Settings.getBoolean(Settings.MAXIMIZE_WITH_GAPS)) { window.tiledRect = null; // It's possible for a window to maximize() to the wrong monitor. // This is very easy to reproduce when dragging a window on the // lower half with Super + LMB. window.move_to_monitor(monitor); window.maximize(Meta.MaximizeFlags.BOTH); return; } // Save the intended tiledRect for accurate operations later. // Workaround for windows which can't be resized freely... // For ex. which only resize in full rows/columns like gnome-terminal window.tiledRect = newRect.copy(); const { x, y, width, height } = newRect.addGaps(workArea, monitor); // Animations const wActor = window.get_compositor_private(); if (Settings.getBoolean(Settings.ENABLE_TILE_ANIMATIONS) && wActor && !skipAnim) { wActor.remove_all_transitions(); // HACK => journalctl: 'error in size change accounting'...? // TODO: no animation if going from maximized -> tiled and back to back multiple times? Main.wm._prepareAnimationInfo( global.window_manager, wActor, oldRect.meta, Meta.SizeChange.MAXIMIZE ); } // See issue #137. // Under some circumstances it's possible that windows will tile to the wrong // monitor. I can't reproduce it but I suspect that it's because of passing // false as the user_op to move_resize_frame. user_op is meant to determine if // the window should be clamped to the monitor. A user operation (user_op = true) // won't be clamped. So I think there is something unexpected happening. // Someone in the issue mentioned that passing true as the user_op fixes the // multi-monitor bug. // // The reason why I set user_op as false originally is that GNOME Terminal (and // some other Terminals) will only resize but not move with user_op as true. Try // to workaround that by first only moving the window and then resizing it. That // workaround was already necessary under Wayland because of some apps. E. g. // first tiling Nautilus and then Firefox using the Tiling Popup. window.move_to_monitor(monitor); window.move_frame(true, x, y); window.move_resize_frame(true, x, y, width, height); // Maximized with gaps if (maximize) { this._updateGappedMaxWindowSignals(window); // Tiled window } else if (!fakeTile) { // Make the tile group only consist of the window itself to stop // resizing or raising together. Also don't call the Tiling Popup. if (Settings.getBoolean(Settings.DISABLE_TILE_GROUPS) || ignoreTA) { this.updateTileGroup([window]); return; } // Setup the (new) tileGroup to raise tiled windows as a group const topTileGroup = this._getWindowsForBuildingTileGroup(monitor); this.updateTileGroup(topTileGroup); this.emit('window-tiled', window); if (openTilingPopup) await this.tryOpeningTilingPopup(); } } /** * Untiles a tiled window and delete all tiling properties. * * @param {Meta.Window} window a Meta.Window to untile. * @param {boolean} [restoreFullPos=true] decides, if we restore the * pre-tile position or whether the size while keeping the titlebar * at the relative same position. * @param {number} [xAnchor=undefined] used when wanting to restore the * size while keeping titlebar at the relative x position. By default, * we use the pointer position. * @param {boolean} [skipAnim=false] decides, if we skip the until animation. */ static untile(window, { restoreFullPos = true, xAnchor = undefined, skipAnim = false, clampToWorkspace = false } = {}) { const wasMaximized = window.get_maximized(); if (wasMaximized) window.unmaximize(wasMaximized); if (!window.untiledRect || !window.allows_resize() || !window.allows_move()) return; // If you tiled a window and then used the popup to tile more // windows, the consecutive windows will be raised above the first // one. So untiling the initial window after tiling more windows with // the popup (without re-focusing the initial window), means the // untiled window will be below the others. if (window.raise_and_make_recent_on_workspace) window.raise_and_make_recent_on_workspace(global.workspace_manager.get_active_workspace()); else window.raise_and_make_recent(); // Animation const untileAnim = Settings.getBoolean(Settings.ENABLE_UNTILE_ANIMATIONS); const wActor = window.get_compositor_private(); if (untileAnim && !wasMaximized && wActor && !skipAnim) { wActor.remove_all_transitions(); Main.wm._prepareAnimationInfo( global.window_manager, wActor, window.get_frame_rect(), Meta.SizeChange.UNMAXIMIZE ); } // userOp means that the window won't clamp to the workspace. For DND // we don't want to clamp to the workspace, so it's false by default. const userOp = !clampToWorkspace; const oldRect = window.untiledRect; if (restoreFullPos) { window.move_resize_frame(userOp, oldRect.x, oldRect.y, oldRect.width, oldRect.height); } else { // Resize the window while keeping the relative x pos (of the pointer) const currWindowFrame = new Rect(window.get_frame_rect()); xAnchor = xAnchor ?? global.get_pointer()[0]; const relativeMouseX = (xAnchor - currWindowFrame.x) / currWindowFrame.width; const newPosX = xAnchor - oldRect.width * relativeMouseX; // Wayland workaround for DND / restore position Meta.is_wayland_compositor() && window.move_frame(true, newPosX, currWindowFrame.y); window.move_resize_frame(userOp, newPosX, currWindowFrame.y, oldRect.width, oldRect.height); } this.clearTilingProps(window.get_id()); window.isTiled = false; window.tiledRect = null; window.untiledRect = null; this.emit('window-untiled', window); } /** * Moves the tile group to a different workspace * * @param {Meta.Window[]} tileGroup * @param {Meta.Workspace} workspace */ static moveGroupToWorkspace(tileGroup, workspace) { tileGroup.forEach(w => { this._blockTilingSignalsFor(w); w.change_workspace(workspace); this._unblockTilingSignalsFor(w); }); } /** * Moves the tile group to a different monitor * * @param {Meta.Window[]} tileGroup * @param {number} oldMon * @param {number} newMon */ static moveGroupToMonitor(tileGroup, oldMon, newMon) { const activeWs = global.workspace_manager.get_active_workspace(); const oldWorkArea = new Rect(activeWs.get_work_area_for_monitor(oldMon)); const newWorkArea = new Rect(activeWs.get_work_area_for_monitor(newMon)); const hScale = oldWorkArea.width / newWorkArea.width; const vScale = oldWorkArea.height / newWorkArea.height; tileGroup.forEach((w, idx) => { const newTile = w.tiledRect.copy(); newTile.x = newWorkArea.x + Math.floor(newWorkArea.width * ((w.tiledRect.x - oldWorkArea.x) / oldWorkArea.width)); newTile.y = newWorkArea.y + Math.floor(newWorkArea.height * ((w.tiledRect.y - oldWorkArea.y) / oldWorkArea.height)); newTile.width = Math.floor(w.tiledRect.width * (1 / hScale)); newTile.height = Math.floor(w.tiledRect.height * (1 / vScale)); // Try to align with all previously scaled tiles and the workspace to prevent gaps for (let i = 0; i < idx; i++) newTile.tryAlignWith(tileGroup[i].tiledRect); newTile.tryAlignWith(newWorkArea, 10); this.tile(w, newTile, { skipAnim: true, fakeTile: true }); }); // The tiling signals got disconnected during the tile() call but not // (re-)connected with it since it may have been possible that wrong tile // groups would have been created when moving one window after the other // to the new monitor. So update the tileGroup now with the full/old group. this.updateTileGroup(tileGroup); } /** * @returns {Map} * For ex: { windowId1: [windowIdX, windowIdY, ...], windowId2: ... } */ static getTileGroups() { return this._tileGroups; } /** * @param {Map} tileGroups * For ex: { windowId1: [windowIdX, windowIdY, ...], windowId2: ... } */ static setTileGroups(tileGroups) { this._tileGroups = tileGroups; } /** * Creates a tile group of windows to raise them together, if one of them * is raised by (re)connecting signals. Usually, this is done automatically * by calling tile() and thus shouldn't be done manually. tile() only allows * unique/non-overlapping tile groups, so 1 window can't be part of multiple * tile groups. But we specifically allow the user to do that sometimes * (i. e. ctrl-drag or tile editing mode+space). So manually create the * tile group in those cases. * * @param {Meta.Windows[]} tileGroup an array of Meta.Windows to group * together. */ static updateTileGroup(tileGroup) { tileGroup.forEach(window => { const windowId = window.get_id(); const signals = this._signals.getSignalsFor(windowId); this._tileGroups.set(windowId, tileGroup.map(w => w.get_id())); /** * clearTilingProps may have been called before this function, * so we need to reconnect all the signals on the tileGroup. * Just in case, also try to disconnect old signals... */ // Reconnect unmanaging signal const unmanagingSignal = signals.get(TilingSignals.UNMANAGING); unmanagingSignal && window.disconnect(unmanagingSignal); const umId = window.connect('unmanaging', w => { this.clearTilingProps(windowId); this._unmanagingWindows.push(w.get_stable_sequence()); }); signals.set(TilingSignals.UNMANAGING, umId); // Reconnect ws-changed signal const wsChangeSignal = signals.get(TilingSignals.WS_CHANGED); wsChangeSignal && window.disconnect(wsChangeSignal); const wsId = window.connect('workspace-changed', () => this._onWindowWorkspaceChanged(window)); signals.set(TilingSignals.WS_CHANGED, wsId); // Reconnect raise signal const raiseSignal = signals.get(TilingSignals.RAISE); raiseSignal && window.disconnect(raiseSignal); const raiseId = window.connect('raised', raisedWindow => { const raisedWindowId = raisedWindow.get_id(); if (Settings.getBoolean(Settings.RAISE_TILE_GROUPS)) { const raisedWindowsTileGroup = this._tileGroups.get(raisedWindowId); raisedWindowsTileGroup.forEach(wId => { const w = this._getWindow(wId); const otherRaiseId = this._signals.getSignalsFor(wId).get(TilingSignals.RAISE); // May be undefined, if w was just closed. This would // automatically call clearTilingProps() with the signal // but in case I missed / don't know about other cases where // w may be nullish, dissolve the tileGroups anyway. if (!w || !otherRaiseId) { this.clearTilingProps(wId); return; } // Prevent an infinite loop of windows raising each other w.block_signal_handler(otherRaiseId); if (w.raise_and_make_recent_on_workspace) w.raise_and_make_recent_on_workspace(global.workspace_manager.get_active_workspace()); else w.raise_and_make_recent(); w.unblock_signal_handler(otherRaiseId); }); // Re-raise the just raised window so it may not be below // other tiled windows otherwise when untiling via keyboard // it may be below other tiled windows. const signalId = this._signals.getSignalsFor(raisedWindowId).get(TilingSignals.RAISE); raisedWindow.block_signal_handler(signalId); if (raisedWindow.raise_and_make_recent_on_workspace) raisedWindow.raise_and_make_recent_on_workspace(global.workspace_manager.get_active_workspace()); else raisedWindow.raise_and_make_recent(); raisedWindow.unblock_signal_handler(signalId); } // Update the tileGroup (and reconnect the raised signals) to allow windows // to be part of multiple tileGroups: for ex.: tiling a window over another // tiled window with ctrl-drag will replace the overlapped window in the old // tileGroup but the overlapped window will remember its old tile group to // raise them as well, if it is raised. const raisedTileGroup = this.getTileGroupFor(raisedWindow); this.updateTileGroup(raisedTileGroup); }); signals.set(TilingSignals.RAISE, raiseId); }); } /** * Deletes the tile group of a window and remove that window from other * tiled windows' tile groups. Also disconnects the signals for windows * which are maximized-with-gaps. * * @param {number} windowId the id of a Meta.Window. */ static clearTilingProps(windowId) { const window = this._getWindow(windowId); const signals = this._signals.getSignalsFor(windowId); if (signals.get(TilingSignals.RAISE)) { window && window.disconnect(signals.get(TilingSignals.RAISE)); signals.set(TilingSignals.RAISE, 0); } if (signals.get(TilingSignals.WS_CHANGED)) { window && window.disconnect(signals.get(TilingSignals.WS_CHANGED)); signals.set(TilingSignals.WS_CHANGED, 0); } if (signals.get(TilingSignals.UNMANAGING)) { window && window.disconnect(signals.get(TilingSignals.UNMANAGING)); signals.set(TilingSignals.UNMANAGING, 0); } if (!this._tileGroups.has(windowId)) return; // Delete window's tileGroup this._tileGroups.delete(windowId); // Delete window from other windows' tileGroup this._tileGroups.forEach(tileGroup => { const idx = tileGroup.indexOf(windowId); idx !== -1 && tileGroup.splice(idx, 1); }); } /** * @param {Meta.Window} window a Meta.Window. * @returns {Meta.Window[]} an array of Meta.Windows, which are in `window`'s * tile group (including the `window` itself). */ static getTileGroupFor(window) { const tileGroup = this._tileGroups.get(window.get_id()); if (!tileGroup) return []; return this._getAllWindows().filter(w => tileGroup.includes(w.get_id())); } /** * Gets the top most tiled window group; that means they complement each * other and don't intersect. This may differ from the TileGroupManager's * *tracked* tile groups since floating windows may overlap some tiled * windows *at the moment* when this function is called. * * @param {boolean} [skipTopWindow=true] whether we ignore the focused window * in the active search for the top tile group. The focused window may * still be part of the returned array if it is part of another high- * stacked window's tile group. This is mainly only useful, if the * focused window isn't tiled (for example when dnd-ing a window). * @param {number} [monitor=null] get the group for the monitor number. * @returns {Meta.Windows[]} an array of tiled Meta.Windows. */ static getTopTileGroup({ skipTopWindow = false, monitor = null } = {}) { // 'Raise Tile Group' setting is enabled so we just return the tracked // tile group. Same thing for the setting 'Disable Tile Groups' because // it's implemented by just making the tile groups consist of single // windows (the tiled window itself). if (Settings.getBoolean(Settings.RAISE_TILE_GROUPS) || Settings.getBoolean(Settings.DISABLE_TILE_GROUPS) ) { const openWindows = this.getWindows(); if (!openWindows.length) return []; if (skipTopWindow) { // the focused window isn't necessarily the top window due to always // on top windows. const idx = openWindows.indexOf(global.display.focus_window); idx !== -1 && openWindows.splice(idx, 1); } const ignoredWindows = []; const mon = monitor ?? global.display.focus_window?.get_monitor() ?? openWindows[0].get_monitor(); for (const window of openWindows) { if (window.get_monitor() !== mon) continue; // Ignore non-tiled windows, which are always-on-top, for the // calculation since they are probably some utility apps etc. if (window.is_above() && !window.isTiled) continue; // Find the first not overlapped tile group, if it exists if (window.isTiled) { const overlapsIgnoredWindow = ignoredWindows.some(w => { const rect = w.tiledRect ?? new Rect(w.get_frame_rect()); return rect.overlap(window.tiledRect); }); if (overlapsIgnoredWindow) ignoredWindows.push(window); else return this.getTileGroupFor(window); } else { ignoredWindows.push(window); } } return []; // 'Raise Tile Group' setting is disabled so we get thetop most // non-overlapped/ing tiled windows ignoring the tile groups. } else { return this._getTopTiledWindows({ skipTopWindow, monitor }); } } /** * Gets the free screen space (1 big Rect). If the free screen space * is ambiguous that means it consists of multiple (unaligned) rectangles * (for ex.: 2 diagonally opposing quarters). In that case we return null. * * @param {Rect[]} rectList an array of Rects, which occupy the screen. * @param {number|null} [monitorNr] useful for the grace period during dnd. * Defaults to pointer monitor. * @returns {Rect|null} a Rect, which represent the free screen space. */ static getFreeScreen(rectList, monitorNr = null) { const activeWs = global.workspace_manager.get_active_workspace(); const monitor = monitorNr ?? global.display.get_current_monitor(); const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); const freeScreenRects = workArea.minus(rectList); if (!freeScreenRects.length) return null; // Create the union of all freeScreenRects and calculate the sum // of their areas. If the area of the union-rect equals the area // of the individual rects, the individual rects align properly. const startRect = new Rect(freeScreenRects[0].x, freeScreenRects[0].y, 0, 0); const { checkSum, combinedRect } = freeScreenRects.reduce((result, rect) => { result.checkSum += rect.area; result.combinedRect = result.combinedRect.union(rect); return result; }, { checkSum: 0, combinedRect: startRect }); if (combinedRect.area !== checkSum) return null; // Random min. size requirement if (combinedRect.width < 250 || combinedRect.height < 250) return null; return combinedRect; } /** * Gets the best available free screen rect. If a `currRect` is passed, * instead this will return an expanded copy of that rect filling all * the available space around it. * * @param {Rect[]} rectList an array of Rects, which occupy the screen. * Like usual, they shouldn't overlap each other. * @param {Rect} [currRect=null] a Rect, which may be expanded. * @param {Orientation} [orientation=null] The orientation we want to expand * `currRect` into. If `null`, expand in both orientations. * @param {Rect} [monitor=null] defaults to pointer monitor. * @returns {Rect} a new Rect. */ static getBestFreeRect(rectList, { currRect = null, orientation = null, monitorNr = null } = {}) { const activeWs = global.workspace_manager.get_active_workspace(); const monitor = monitorNr ?? global.display.get_current_monitor(); const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); const freeRects = workArea.minus(rectList); if (!freeRects.length) return currRect ?? new Rect(workArea); // Try to expand the currRect to fill the rest of the space // that is available around it. if (currRect) { const isVert = (orientation ?? Orientation.V) === Orientation.V; const [xpndPos1, xpndPos2] = isVert ? ['y', 'y2'] : ['x', 'x2']; const [unxpndPos1, unxpndPos2] = isVert ? ['x', 'x2'] : ['y', 'y2']; // Filter the rects to only keep the ones directly bordering the // currRect and sort the array so that the free rects are ordered // from the left to the right or from the top to the bottom. See // below for the reasoning. const borderingRects = freeRects.filter(r => { const axis1 = currRect[xpndPos1] === r[xpndPos2] || currRect[xpndPos2] === r[xpndPos1]; const axis2 = isVert ? currRect.horizOverlap(r) : currRect.vertOverlap(r); return axis1 && axis2; }).sort((a, b) => a[unxpndPos1] - b[unxpndPos1]); // Separate the rects into the ones that come before (left / top) // or after (right / bottom) the current rect. const { before, after } = borderingRects.reduce((result, r) => { if (currRect[xpndPos1] === r[xpndPos2]) result.before.push(r); else if (currRect[xpndPos2] === r[xpndPos1]) result.after.push(r); return result; }, { before: [], after: [] }); // If we want to check whether the current rect can expand on a certain // side (let's say we expand the height), we need to check the *other* // (unexpanded) side. So whether the current rect is bordering the free // screen rects along its *entire width*. We do this by 'union-ing' the // free screen rects along the relevant side (our ex.: width). For this // reason we needed to sort the free rects in ascending order before // to make sure they overlap before trying to 'union' them. After the // union-ing, we just check, if the union-ed rect contains the current // rects unexpanded side. // Orientation doesn't matter here since we are always comparing sides // of the same orientation. So just make the side always horizontal. const makeSide = (startPoint, endPoint) => new Mtk.Rectangle({ x: startPoint, width: endPoint - startPoint, height: 1 }); const freeRectsContainCurrRectSide = rects => { const currRectSide = makeSide(currRect[unxpndPos1], currRect[unxpndPos2]); const linkedSides = rects.reduce((linked, r) => { const side = makeSide(r[unxpndPos1], r[unxpndPos2]); return linked.overlap(side) ? linked.union(side) : linked; }, makeSide(rects[0][unxpndPos1], rects[0][unxpndPos2])); return linkedSides.contains_rect(currRectSide); }; const newRect = currRect.copy(); // Expand to the left / top. if (before.length) { if (freeRectsContainCurrRectSide(before)) { const expandStartTo = before.reduce((currSize, rect) => { return Math.max(currSize, rect[xpndPos1]); }, before[0][xpndPos1]); newRect[xpndPos2] += newRect[xpndPos1] - expandStartTo; newRect[xpndPos1] = expandStartTo; } } // Expand to the right / bottom. if (after.length) { if (freeRectsContainCurrRectSide(after)) { const expandEndTo = after.reduce((currSize, rect) => { return Math.min(currSize, rect[xpndPos2]); }, after[0][xpndPos2]); newRect[xpndPos2] = expandEndTo; } } if (!orientation) { // if orientation is null, we expanded vertically. Now we want // to expand horizontally as well. rectList = [...rectList]; const currRectIdx = rectList.findIndex(r => r.equal(currRect)); rectList.splice(currRectIdx, 1); rectList.push(newRect); return newRect.union( this.getBestFreeRect(rectList, { currRect: newRect, orientation: Orientation.H, monitorNr: monitor })); } else { return newRect; } // No currRect was passed, so we just choose the single biggest free rect // and expand it using this function. This is a naive approach and doesn't // guarantee that we get the best combination of free screen rects... but // it should be good enough. } else { const biggestSingle = freeRects.reduce((currBiggest, rect) => { return currBiggest.area >= rect.area ? currBiggest : rect; }); rectList.push(biggestSingle); return this.getBestFreeRect(rectList, { currRect: biggestSingle }); } } /** * Gets the nearest Meta.Window in the direction of `dir`. * * @param {Meta.Windows} currWindow the Meta.Window that the search starts * from. * @param {Meta.Windows[]} windows an array of the available Meta.Windows. * It may contain the current window itself. The windows shouldn't * overlap each other. * @param {Direction} dir the direction that is look into. * @param {boolean} [wrap=true] whether we wrap around, * if there is no Meta.Window in the direction of `dir`. * @returns {Meta.Window|null} the nearest Meta.Window. */ static getNearestWindow(currWindow, windows, dir, wrap = true) { const getRect = w => w.tiledRect ?? new Rect(w.get_frame_rect()); const rects = windows.map(w => getRect(w)); const nearestRect = getRect(currWindow).getNeighbor(dir, rects, wrap); if (!nearestRect) return null; return windows.find(w => getRect(w).equal(nearestRect)); } /** * Gets the rectangle for special positions adapted to the surrounding * rectangles. The position is determined by `shortcut` but this function * isn't limited to just keyboard shortcuts. This is also used when * dnd-ing a window. * * Examples: Shortcuts.LEFT gets the left-most rectangle with the height * of the workArea. Shortcuts.BOTTOM_LEFT gets the rectangle touching the * bottom left screen corner etc... If there is no other rect to adapt to * we default to half the workArea. * * @param {Shortcuts} shortcut the side / quarter to get the tile rect for. * @param {Rect} workArea the workArea. * @param {number} [monitor=null] the monitor number we want to get the * rect for. This may not always be the current monitor. It is only * used to implement the 'grace period' to enable quickly tiling a * window using the screen edges even if there is another monitor * at that edge. * @returns a Rect. */ static getTileFor(shortcut, workArea, monitor = null) { // Don't try to adapt a tile rect if (Settings.getBoolean(Settings.DISABLE_TILE_GROUPS)) return this.getDefaultTileFor(shortcut, workArea); const topTileGroup = this.getTopTileGroup({ skipTopWindow: true, monitor }); // getTileFor is used to get the adaptive tiles for dnd & tiling keyboard // shortcuts. That's why the top most window needs to be ignored when // calculating the new tile rect. The top most window is already ignored // for dnd in the getTopTileGroup() call. While the top most window will // be ignored for the active search in getTopTileGroup, it may still be // part of the returned array if it's part of another high-stackeing // window's tile group. const idx = topTileGroup.indexOf(global.display.focus_window); idx !== -1 && topTileGroup.splice(idx, 1); const favLayout = Util.getFavoriteLayout(monitor); const useFavLayout = favLayout.length && Settings.getBoolean(Settings.ADAPT_EDGE_TILING_TO_FAVORITE_LAYOUT); const twRects = useFavLayout && favLayout || topTileGroup.map(w => w.tiledRect); if (!twRects.length) return this.getDefaultTileFor(shortcut, workArea); // Return the adapted rect only if it doesn't overlap an existing tile. // Ignore an overlap, if a fav layout is used since we always prefer the // user set layout in that case. const getTile = rect => { if (useFavLayout) return rect; const overlapsTiles = twRects.some(r => r.overlap(rect)); return overlapsTiles ? this.getDefaultTileFor(shortcut, workArea) : rect; }; const screenRects = twRects.concat(workArea.minus(twRects)); switch (shortcut) { case Shortcuts.MAXIMIZE: { return workArea.copy(); } case Shortcuts.LEFT: { const left = screenRects.find(r => r.x === workArea.x && r.width !== workArea.width); const { width } = left ?? workArea.getUnitAt(0, workArea.width / 2, Orientation.V); const result = new Rect(workArea.x, workArea.y, width, workArea.height); return getTile(result); } case Shortcuts.RIGHT: { const right = screenRects.find(r => r.x2 === workArea.x2 && r.width !== workArea.width); const { width } = right ?? workArea.getUnitAt(1, workArea.width / 2, Orientation.V); const result = new Rect(workArea.x2 - width, workArea.y, width, workArea.height); return getTile(result); } case Shortcuts.TOP: { const top = screenRects.find(r => r.y === workArea.y && r.height !== workArea.height); const { height } = top ?? workArea.getUnitAt(0, workArea.height / 2, Orientation.H); const result = new Rect(workArea.x, workArea.y, workArea.width, height); return getTile(result); } case Shortcuts.BOTTOM: { const bottom = screenRects.find(r => r.y2 === workArea.y2 && r.height !== workArea.height); const { height } = bottom ?? workArea.getUnitAt(1, workArea.height / 2, Orientation.H); const result = new Rect(workArea.x, workArea.y2 - height, workArea.width, height); return getTile(result); } case Shortcuts.TOP_LEFT: { const left = screenRects.find(r => r.x === workArea.x && r.width !== workArea.width); const { width } = left ?? workArea.getUnitAt(0, workArea.width / 2, Orientation.V); const top = screenRects.find(r => r.y === workArea.y && r.height !== workArea.height); const { height } = top ?? workArea.getUnitAt(0, workArea.height / 2, Orientation.H); const result = new Rect(workArea.x, workArea.y, width, height); return getTile(result); } case Shortcuts.TOP_RIGHT: { const right = screenRects.find(r => r.x2 === workArea.x2 && r.width !== workArea.width); const { width } = right ?? workArea.getUnitAt(1, workArea.width / 2, Orientation.V); const top = screenRects.find(r => r.y === workArea.y && r.height !== workArea.height); const { height } = top ?? workArea.getUnitAt(0, workArea.height / 2, Orientation.H); const result = new Rect(workArea.x2 - width, workArea.y, width, height); return getTile(result); } case Shortcuts.BOTTOM_LEFT: { const left = screenRects.find(r => r.x === workArea.x && r.width !== workArea.width); const { width } = left ?? workArea.getUnitAt(0, workArea.width / 2, Orientation.V); const bottom = screenRects.find(r => r.y2 === workArea.y2 && r.height !== workArea.height); const { height } = bottom ?? workArea.getUnitAt(1, workArea.height / 2, Orientation.H); const result = new Rect(workArea.x, workArea.y2 - height, width, height); return getTile(result); } case Shortcuts.BOTTOM_RIGHT: { const right = screenRects.find(r => r.x2 === workArea.x2 && r.width !== workArea.width); const { width } = right ?? workArea.getUnitAt(1, workArea.width / 2, Orientation.V); const bottom = screenRects.find(r => r.y2 === workArea.y2 && r.height !== workArea.height); const { height } = bottom ?? workArea.getUnitAt(1, workArea.height / 2, Orientation.H); const result = new Rect(workArea.x2 - width, workArea.y2 - height, width, height); return getTile(result); } } } /** * @param {Shortcuts} shortcut determines, which half/quarter to get the tile for * @param {Rect} workArea * @returns */ static getDefaultTileFor(shortcut, workArea) { switch (shortcut) { case Shortcuts.MAXIMIZE: return workArea.copy(); case Shortcuts.LEFT: case Shortcuts.LEFT_IGNORE_TA: return workArea.getUnitAt(0, workArea.width / 2, Orientation.V); case Shortcuts.RIGHT: case Shortcuts.RIGHT_IGNORE_TA: return workArea.getUnitAt(1, workArea.width / 2, Orientation.V); case Shortcuts.TOP: case Shortcuts.TOP_IGNORE_TA: return workArea.getUnitAt(0, workArea.height / 2, Orientation.H); case Shortcuts.BOTTOM: case Shortcuts.BOTTOM_IGNORE_TA: return workArea.getUnitAt(1, workArea.height / 2, Orientation.H); case Shortcuts.TOP_LEFT: case Shortcuts.TOP_LEFT_IGNORE_TA: return workArea.getUnitAt(0, workArea.width / 2, Orientation.V).getUnitAt(0, workArea.height / 2, Orientation.H); case Shortcuts.TOP_RIGHT: case Shortcuts.TOP_RIGHT_IGNORE_TA: return workArea.getUnitAt(1, workArea.width / 2, Orientation.V).getUnitAt(0, workArea.height / 2, Orientation.H); case Shortcuts.BOTTOM_LEFT: case Shortcuts.BOTTOM_LEFT_IGNORE_TA: return workArea.getUnitAt(0, workArea.width / 2, Orientation.V).getUnitAt(1, workArea.height / 2, Orientation.H); case Shortcuts.BOTTOM_RIGHT: case Shortcuts.BOTTOM_RIGHT_IGNORE_TA: return workArea.getUnitAt(1, workArea.width / 2, Orientation.V).getUnitAt(1, workArea.height / 2, Orientation.H); } } /** * Opens the Tiling Popup, if there is unambiguous free screen space, * and offer to tile an open window to that spot. */ static async tryOpeningTilingPopup() { if (!Settings.getBoolean(Settings.ENABLE_TILING_POPUP)) return; const allWs = Settings.getBoolean(Settings.POPUP_ALL_WORKSPACES); const openWindows = this.getWindows(allWs); const topTileGroup = this.getTopTileGroup(); topTileGroup.forEach(w => openWindows.splice(openWindows.indexOf(w), 1)); if (!openWindows.length) return; const tRects = topTileGroup.map(w => w.tiledRect); const monitor = topTileGroup[0]?.get_monitor(); // for the grace period const freeSpace = this.getFreeScreen(tRects, monitor); if (!freeSpace) return; const TilingPopup = await import('./tilingPopup.js'); const popup = new TilingPopup.TilingSwitcherPopup(openWindows, freeSpace); if (!popup.show(topTileGroup)) popup.destroy(); } /** * Tiles or untiles a window based on its current tiling state. * * @param {Meta.Window} window a Meta.Window. * @param {Rect} rect the Rect the `window` tiles to or untiles from. */ static toggleTiling(window, rect, params = {}) { const workArea = window.get_work_area_current_monitor(); const equalsWA = rect.equal(workArea); const equalsTile = window.tiledRect && rect.equal(window.tiledRect); if (window.isTiled && equalsTile || this.isMaximized(window) && equalsWA) this.untile(window, params); else this.tile(window, rect, params); } /** * Tries to open an app on a tiling state (in a very dumb way...). * * @param {Shell.App} app the Shell.App to open and tile. * @param {Rect} rect the Rect to tile to. * @param {boolean} [openTilingPopup=false] allow the Tiling Popup to * appear, if there is free screen space after the `app` was tiled. */ static openAppTiled(app, rect, openTilingPopup = false) { if (!app?.can_open_new_window()) return; let createId = global.display.connect('window-created', (src, window) => { const wActor = window.get_compositor_private(); let firstFrameId = wActor?.connect('first-frame', () => { wActor.disconnect(firstFrameId); firstFrameId = 0; const winTracker = Shell.WindowTracker.get_default(); const openedWindowApp = winTracker.get_window_app(window); // Check, if the created window is from the app and if it allows // to be moved and resized because, for example, Steam uses a // WindowType.Normal window for their loading screen, which we // don't want to trigger the tiling for. if (createId && openedWindowApp && openedWindowApp === app && (window.allows_resize() && window.allows_move() || window.get_maximized()) ) { global.display.disconnect(createId); createId = 0; this.tile(window, rect, { openTilingPopup, skipAnim: true }); } }); // Don't immediately disconnect the signal in case the launched // window doesn't match the original app. It may be a loading screen // or the user started an app in between etc... but in case the checks/ // signals above fail disconnect the signals after 1 min at the latest this._openAppTiledTimerId && GLib.Source.remove(this._openAppTiledTimerId); this._openAppTiledTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 60000, () => { createId && global.display.disconnect(createId); createId = 0; firstFrameId && wActor.disconnect(firstFrameId); firstFrameId = 0; this._openAppTiledTimerId = null; return GLib.SOURCE_REMOVE; }); }); app.open_new_window(-1); } /** * Gets the top windows, which are supposed to be in a tile group. That * means windows, which are tiled, and don't overlap each other. */ static _getWindowsForBuildingTileGroup(monitor = null) { const openWindows = this.getWindows(); if (!openWindows.length) return []; const ignoredWindows = []; const result = []; const mon = monitor ?? global.display.focus_window?.get_monitor() ?? openWindows[0].get_monitor(); for (const window of openWindows) { if (window.get_monitor() !== mon) continue; if (window.is_above() && !window.isTiled) continue; if (window.isTiled) { // Window was already checked as part of another's tileGroup. if (ignoredWindows.includes(window) || result.includes(window)) continue; // Check for the other windows in the tile group as well regardless // of the 'raise tile group' setting so that once the setting is // enabled the tile groups are already set properly. const tileGroup = this.getTileGroupFor(window); // This means `window` is the window that was just tiled and // thus has no tileGroup set at this point yet. if (!tileGroup.length) { result.push(window); continue; } const tileGroupOverlaps = tileGroup.some(w => result.some(r => r.tiledRect.overlap(w.tiledRect)) || ignoredWindows.some(r => (r.tiledRect ?? new Rect(r.get_frame_rect())).overlap(w.tiledRect))); tileGroupOverlaps ? tileGroup.forEach(w => ignoredWindows.push(w)) : tileGroup.forEach(w => result.push(w)); } else { // The window is maximized, so all windows below it can't belong // to this group anymore. if (this.isMaximized(window)) break; ignoredWindows.push(window); } } return result; } /** * Gets the top most non-overlapped/ing tiled windows ignoring * the stacking order and tile groups. * * @param {{boolean, number}} param1 */ static _getTopTiledWindows({ skipTopWindow = false, monitor = null } = {}) { const openWindows = this.getWindows(); if (!openWindows.length) return []; if (skipTopWindow) { // the focused window isn't necessarily the top window due to always // on top windows. const idx = openWindows.indexOf(global.display.focus_window); idx !== -1 && openWindows.splice(idx, 1); } const topTiledWindows = []; const ignoredWindows = []; const mon = monitor ?? global.display.focus_window?.get_monitor() ?? openWindows[0].get_monitor(); for (const window of openWindows) { if (window.get_monitor() !== mon) continue; if (window.is_above() && !window.isTiled) continue; if (window.isTiled) { const wRect = window.tiledRect; // If a ignored window in a higher stack order overlaps the // currently tested tiled window, the currently tested tiled // window isn't part of the top tile group. const overlapsIgnoredWindow = ignoredWindows.some(w => { const rect = w.tiledRect ?? new Rect(w.get_frame_rect()); return rect.overlap(wRect); }); // Same applies for already grouped windows const overlapsTopTiledWindows = topTiledWindows.some(w => w.tiledRect.overlap(wRect)); overlapsIgnoredWindow || overlapsTopTiledWindows ? ignoredWindows.push(window) : topTiledWindows.push(window); } else { // The window is maximized, so all windows below it can't belong // to this group anymore. if (this.isMaximized(window)) break; ignoredWindows.push(window); } } return topTiledWindows; } /** * Blocks all tiling signals for a window. * * @param {Meta.Window} window */ static _blockTilingSignalsFor(window) { const signals = this._signals.getSignalsFor(window.get_id()); const blockedSignals = [TilingSignals.RAISE, TilingSignals.WS_CHANGED, TilingSignals.UNMANAGING]; blockedSignals.forEach(s => { const id = signals.get(s); id && window.block_signal_handler(id); }); } /** * Unblocks all tiling signals for a window. * Should only be called after _blockTilingSignalsFor(). * * @param {Meta.Window} window */ static _unblockTilingSignalsFor(window) { const signals = this._signals.getSignalsFor(window.get_id()); const blockedSignals = [TilingSignals.RAISE, TilingSignals.WS_CHANGED, TilingSignals.UNMANAGING]; blockedSignals.forEach(s => { const id = signals.get(s); id && window.unblock_signal_handler(id); }); } /** * Updates the signals after maximizing a window with gaps. * * @param {Meta.Window} window */ static _updateGappedMaxWindowSignals(window) { const wId = window.get_id(); const signals = this._signals.getSignalsFor(wId); // Refresh 'unmanaging' signal const unmanagingSignal = signals.get(TilingSignals.UNMANAGING); unmanagingSignal && window.disconnect(unmanagingSignal); const umId = window.connect('unmanaging', w => { this.clearTilingProps(window.get_id()); this._unmanagingWindows.push(w.get_stable_sequence()); }); signals.set(TilingSignals.UNMANAGING, umId); // Refresh 'workspace-changed' signal const wsId = window.connect('workspace-changed', () => this._onWindowWorkspaceChanged(window)); this._signals.getSignalsFor(wId).set(TilingSignals.WS_CHANGED, wsId); } /** * @returns {Meta.Window[]} an array of *all* windows * (and not just the ones relevant to altTab) */ static _getAllWindows() { return global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null); } /** * Gets the window matching a window id * * @param {number} id * @returns {Meta.Window} */ static _getWindow(id) { return this._getAllWindows().find(w => w.get_id() === id); } /** * A window's workspace-changed signal is used to untile it when the user * changes its workspace. However, dynamic workspaces *may* also trigger a * ws-changed signal. So listen to the workspace-added/removed signals and * 'ignore' the next ws-changed signal. A ws addition/removal doesn't guarantuee * a ws-changed signal (e. g. the workspace is at the end), so reset after * a short timer. */ static _onWorkspaceAdded() { this._ignoreWsChange = true; this._wsAddedTimer && GLib.Source.remove(this._wsAddedTimer); this._wsAddedTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 50, () => { this._ignoreWsChange = false; this._wsAddedTimer = null; return GLib.SOURCE_REMOVE; }); } /** * A window's workspace-changed signal is used to untile it when the user * changes its workspace. However, dynamic workspaces *may* also trigger a * ws-changed signal. So listen to the workspace-added/removed signals and * 'ignore' the next ws-changed signal. A ws addition/removal doesn't guarantuee * a ws-changed signal (e. g. the workspace is at the end), so reset after * a short timer. */ static _onWorkspaceRemoved() { this._ignoreWsChange = true; this._wsRemovedTimer && GLib.Source.remove(this._wsRemovedTimer); this._wsRemovedTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 50, () => { this._ignoreWsChange = false; this._wsRemovedTimer = null; return GLib.SOURCE_REMOVE; }); } /** * This is only called for tiled and maximized (with gaps) windows. * Untile tiled windows. Re-tile maximized windows to fit the whole workArea * since a monitor change will also trigger a workspace-change signal. * Previously, we tried to adapt the tiled window's size to the new monitor * but that is probably too unpredictable. First, it may introduce rounding * errors when moving multiple windows of the same tileGroup and second (and * more importantly) the behavior with regards to tileGroups isn't clear... * Should the entire tileGroup move, if 1 tiled window is moved? If not, * there should probably be a way to just detach 1 window from a group. What * happens on the new monitor, if 1 window is moved? Should it create a new * tileGroup? Should it try to integrate into existing tileGroups on that * monitor etc... there are too many open questions. Instead just untile * and leave it up to the user to re-tile a window. * * @param {Meta.Window} window */ static _onWindowWorkspaceChanged(window) { // Closing a window triggers a ws-changed signal, which may lead to a // crash, if we try to operate on it any further. So we listen to the // 'unmanaging'-signal to see, if there is a 'true workspace change' // or whether the window was just closed if (this._unmanagingWindows.includes(window.get_stable_sequence())) return; if (this._ignoreWsChange) return; if (this.isMaximized(window)) { const wA = window.get_work_area_for_monitor(window.get_monitor()); const workArea = new Rect(wA); if (workArea.equal(window.tiledRect)) return; this.tile(window, workArea, { openTilingPopup: false, skipAnim: true }); } else if (window.isTiled) { this.untile(window, { restoreFullPos: false, clampToWorkspace: true, skipAnim: Main.overview.visible }); } } } /** * This is instanced by the 'TilingWindowManager'. It implements the tiling * signals and tracks the signal( id)s, which are relevant for tiling: * Raise: for group raising. * Ws-changed: for untiling a tiled window after its ws changed. * Unmanaging: to remove unmanaging tiled windows from the other tileGroups. */ const TilingSignals = GObject.registerClass({ Signals: { 'window-tiled': { param_types: [Meta.Window.$gtype] }, 'window-untiled': { param_types: [Meta.Window.$gtype] } } }, class TilingSignals extends Clutter.Actor { // Relevant 'signal types' (sorta used as an enum / key for the signal map). // Tiled windows use all 3 signals; maximized-with-gaps windows only use the // workspace-changed and unmanaging signal. static RAISE = 'RAISE'; static WS_CHANGED = 'WS_CHANGED'; static UNMANAGING = 'UNMANAGING'; _init() { super._init(); // { windowId1: { RAISE: signalId1, WS_CHANGED: signalId2, UNMANAGING: signalId3 }, ... } this._ids = new Map(); } destroy() { // Disconnect remaining signals const allWindows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null); this._ids.forEach((signals, windowId) => { const window = allWindows.find(w => w.get_id() === windowId); window && signals.forEach(s => s && window.disconnect(s)); }); super.destroy(); } /** * Gets the signal ids for the raise, ws-changed and unmanaging signals * for a specific window * * @param {number} windowId Meta.Window's id * @returns {Map} the tiling signal ids for the window (id) * with a 'signal type' as the keys */ getSignalsFor(windowId) { let ret = this._ids.get(windowId); if (!ret) { ret = new Map(); this._ids.set(windowId, ret); } return ret; } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/extension/utility.js000066400000000000000000000645271457776040200300560ustar00rootroot00000000000000import { Clutter, Gio, GLib, Mtk, St } from '../dependencies/gi.js'; import { Main } from '../dependencies/shell.js'; import { Direction, Orientation, Settings } from '../common.js'; /** * Library of commonly used functions for the extension.js' files * (and *not* the prefs files) */ export class Util { /** * Performs an approximate equality check. There will be times when * there will be inaccuracies. For example, the user may enable window * gaps and resize 2 tiled windows and try to line them up manually. * But since the gaps are implemented with this extension, there will * be no window snapping. So the windows won't be aligned pixel * perfectly... in that case we first check approximately and correct * the inaccuracies afterwards. * * @param {number} value * @param {number} value2 * @param {number} [margin=4] * @returns {boolean} whether the values are approximately equal. */ static equal(value, value2, margin = 4) { return Math.abs(value - value2) <= margin; } /** * @param {{x, y}} pointA * @param {{x, y}} pointB * @returns {number} the distance between `pointA` and `pointB`, */ static getDistance(pointA, pointB) { const diffX = pointA.x - pointB.x; const diffY = pointA.y - pointB.y; return Math.sqrt(diffX * diffX + diffY * diffY); } /** * @param {number} keyVal * @param {Direction} direction * @returns {boolean} whether the `keyVal` is considered to be in the * direction of `direction`. */ static isDirection(keyVal, direction) { switch (direction) { case Direction.N: return keyVal === Clutter.KEY_Up || keyVal === Clutter.KEY_w || keyVal === Clutter.KEY_W || keyVal === Clutter.KEY_k || keyVal === Clutter.KEY_K; case Direction.S: return keyVal === Clutter.KEY_Down || keyVal === Clutter.KEY_s || keyVal === Clutter.KEY_S || keyVal === Clutter.KEY_j || keyVal === Clutter.KEY_J; case Direction.W: return keyVal === Clutter.KEY_Left || keyVal === Clutter.KEY_a || keyVal === Clutter.KEY_A || keyVal === Clutter.KEY_h || keyVal === Clutter.KEY_H; case Direction.E: return keyVal === Clutter.KEY_Right || keyVal === Clutter.KEY_d || keyVal === Clutter.KEY_D || keyVal === Clutter.KEY_l || keyVal === Clutter.KEY_L; } return false; } /** * @param {number} keyVal * @returns {Direction} */ static getDirection(keyVal) { if (this.isDirection(keyVal, Direction.N)) return Direction.N; else if (this.isDirection(keyVal, Direction.S)) return Direction.S; else if (this.isDirection(keyVal, Direction.W)) return Direction.W; else if (this.isDirection(keyVal, Direction.E)) return Direction.E; else return null; } /** * Get the window or screen gaps scaled to the monitor scale. * * @param {String} settingsKey the key for the gap * @param {number} monitor the number of the monitor to scale the gap to * @returns {number} the scaled gap as a even number since the window gap * will be divided by 2. */ static getScaledGap(settingsKey, monitor) { const gap = Settings.getInt(settingsKey); const scaledGap = gap * global.display.get_monitor_scale(monitor); return scaledGap % 2 === 0 ? scaledGap : scaledGap + 1; } static useIndividualGaps(monitor) { // Prefer individual gaps over the single one const screenTopGap = this.getScaledGap(Settings.SCREEN_TOP_GAP, monitor); const screenLeftGap = this.getScaledGap(Settings.SCREEN_LEFT_GAP, monitor); const screenRightGap = this.getScaledGap(Settings.SCREEN_RIGHT_GAP, monitor); const screenBottomGap = this.getScaledGap(Settings.SCREEN_BOTTOM_GAP, monitor); return screenTopGap || screenLeftGap || screenRightGap || screenBottomGap; } /** * @param {number} modMask a Clutter.ModifierType. * @returns whether the current event the modifier at `modMask`. */ static isModPressed(modMask) { return global.get_pointer()[2] & modMask; } /** * @returns {Layout[]} the layouts */ static getLayouts() { const userDir = GLib.get_user_config_dir(); const pathArr = [userDir, '/tiling-assistant/layouts.json']; const path = GLib.build_filenamev(pathArr); const file = Gio.File.new_for_path(path); if (!file.query_exists(null)) return []; const [success, contents] = file.load_contents(null); if (!success || !contents.length) return []; return JSON.parse(new TextDecoder().decode(contents)); } /** * @param {number|null} monitorNr determines which monitor the layout scales * to. Sometimes we want the monitor of the pointer (when using dnd) and * sometimes not (when using layouts with the keyboard shortcuts). * @returns {Rect[]} */ static getFavoriteLayout(monitorNr = null) { // I don't know when the layout may have changed on the disk(?), // so always get it anew. const monitor = monitorNr ?? global.display.get_current_monitor(); const favoriteLayout = []; const layouts = this.getLayouts(); const layout = layouts?.[Settings.getStrv(Settings.FAVORITE_LAYOUTS)[monitor]]; if (!layout) return []; const activeWs = global.workspace_manager.get_active_workspace(); const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); // Scale the rect's ratios to the workArea. Try to align the rects to // each other and the workArea to workaround possible rounding errors // due to the scaling. layout._items.forEach(({ rect: rectRatios }, idx) => { const rect = new Rect( workArea.x + Math.floor(rectRatios.x * workArea.width), workArea.y + Math.floor(rectRatios.y * workArea.height), Math.ceil(rectRatios.width * workArea.width), Math.ceil(rectRatios.height * workArea.height) ); favoriteLayout.push(rect); for (let i = 0; i < idx; i++) rect.tryAlignWith(favoriteLayout[i]); }); favoriteLayout.forEach(rect => rect.tryAlignWith(workArea)); return favoriteLayout; } /** * Shows the tiled rects of the top tile group. * * @returns {St.Widget[]} an array of St.Widgets to indicate the tiled rects. */ static async ___debugShowTiledRects() { const twm = (await import('./tilingWindowManager.js')).TilingWindowManager; const topTileGroup = twm.getTopTileGroup(); if (!topTileGroup.length) { Main.notify('Tiling Assistant', 'No tiled windows / tiled rects.'); return null; } const indicators = []; topTileGroup.forEach(w => { const indicator = new St.Widget({ style_class: 'tile-preview', opacity: 160, x: w.tiledRect.x, y: w.tiledRect.y, width: w.tiledRect.width, height: w.tiledRect.height }); Main.uiGroup.add_child(indicator); indicators.push(indicator); }); return indicators; } /** * Shows the free screen rects based on the top tile group. * * @returns {St.Widget[]} an array of St.Widgets to indicate the free * screen rects. */ static async ___debugShowFreeScreenRects() { const activeWs = global.workspace_manager.get_active_workspace(); const monitor = global.display.get_current_monitor(); const workArea = new Rect(activeWs.get_work_area_for_monitor(monitor)); const twm = (await import('./tilingWindowManager.js')).TilingWindowManager; const topTileGroup = twm.getTopTileGroup(); const tRects = topTileGroup.map(w => w.tiledRect); const freeScreenSpace = twm.getFreeScreen(tRects); const rects = freeScreenSpace ? [freeScreenSpace] : workArea.minus(tRects); if (!rects.length) { Main.notify('Tiling Assistant', 'No free screen rects to show.'); return null; } const indicators = []; rects.forEach(rect => { const indicator = new St.Widget({ style_class: 'tile-preview', x: rect.x, y: rect.y, width: rect.width, height: rect.height }); Main.uiGroup.add_child(indicator); indicators.push(indicator); }); return indicators.length ? indicators : null; } /** * Print the tile groups to the logs. */ static async __debugPrintTileGroups() { log('--- Tiling Assistant: Start ---'); const twm = await import('./tilingWindowManager.js'); const openWindows = twm.getWindows(); openWindows.forEach(w => { if (!w.isTiled) return; log(`Tile group for: ${w.get_wm_class()}`); const tileGroup = twm.getTileGroupFor(w); tileGroup.forEach(tw => log(tw.get_wm_class())); log('---'); }); log('--- Tiling Assistant: End ---'); } } /** * Wrapper for Mtk.Rectangle to add some more functions. */ export class Rect { /** * @param {...any} params No parameters, 1 Mtk.Rectangle or the x, y, * width and height values should be passed to the constructor. */ constructor(...params) { this._rect = new Mtk.Rectangle(); switch (params.length) { case 0: break; case 1: this._rect.x = params[0].x; this._rect.y = params[0].y; this._rect.width = params[0].width; this._rect.height = params[0].height; break; case 4: this._rect.x = params[0]; this._rect.y = params[1]; this._rect.width = params[2]; this._rect.height = params[3]; break; default: log('Tiling Assistant: Invalid param count for Rect constructor!'); } } /** * Gets a new rectangle where the screen and window gaps were * added/subbed to/from `this`. * * @param {Rect} rect a tiled Rect * @param {number} monitor the number of the monitor to scale the gap to * @returns {Rect} the rectangle after the gaps were taken into account */ addGaps(workArea, monitor) { const screenTopGap = Util.getScaledGap(Settings.SCREEN_TOP_GAP, monitor); const screenLeftGap = Util.getScaledGap(Settings.SCREEN_LEFT_GAP, monitor); const screenRightGap = Util.getScaledGap(Settings.SCREEN_RIGHT_GAP, monitor); const screenBottomGap = Util.getScaledGap(Settings.SCREEN_BOTTOM_GAP, monitor); const singleScreenGap = Util.getScaledGap(Settings.SINGLE_SCREEN_GAP, monitor); const windowGap = Util.getScaledGap(Settings.WINDOW_GAP, monitor); const r = this.copy(); // Prefer individual gaps if (Util.useIndividualGaps(monitor)) { [['x', 'width', screenLeftGap, screenRightGap], ['y', 'height', screenTopGap, screenBottomGap]] .forEach(([pos, dim, posGap, dimGap]) => { if (this[pos] === workArea[pos]) { r[pos] = this[pos] + posGap; r[dim] -= posGap; } else { r[pos] = this[pos] + windowGap / 2; r[dim] -= windowGap / 2; } if (this[pos] + this[dim] === workArea[pos] + workArea[dim]) r[dim] -= dimGap; else r[dim] -= windowGap / 2; }); // Use the single screen gap } else { [['x', 'width'], ['y', 'height']].forEach(([pos, dim]) => { if (this[pos] === workArea[pos]) { r[pos] = this[pos] + singleScreenGap; r[dim] -= singleScreenGap; } else { r[pos] = this[pos] + windowGap / 2; r[dim] -= windowGap / 2; } if (this[pos] + this[dim] === workArea[pos] + workArea[dim]) r[dim] -= singleScreenGap; else r[dim] -= windowGap / 2; }); } return r; } /** * Checks whether `this` borders another rectangle on this' east edge. * * @param {Rect} rect * @returns {boolean} */ bordersOnE(rect) { return this.vertOverlap && this.x2 === rect.x; } /** * Checks whether `this` borders another rectangle on this' south edge. * * @param {Rect} rect * @returns {boolean} */ bordersOnS(rect) { return this.horizOverlap && this.y2 === rect.y; } /** * @param {{x: number, y: number}} point * @returns {boolean} */ containsPoint(point) { return point.x >= this.x && point.x <= this.x2 && point.y >= this.y && point.y <= this.y2; } /** * @param {Rect} rect * @returns {boolean} */ containsRect(rect) { rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; return this._rect.contains_rect(rect); } /** * @returns {Rect} */ copy() { return new Rect(this._rect); } /** * @param {Rect} rect * @returns {boolean} */ couldFitRect(rect) { rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; return this._rect.could_fit_rect(rect); } /** * @param {Rect} rect * @returns {boolean} */ equal(rect) { rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; return this._rect.equal(rect); } /** * Gets the neighbor in the direction `dir` within the list of Rects * `rects`. * * @param {Direction} dir the direction that is looked into. * @param {Rect[]} rects an array of the available Rects. It may contain * `this` itself. The rects shouldn't overlap each other. * @param {boolean} [wrap=true] whether wrap is enabled, * if there is no Rect in the direction of `dir`. * @returns {Rect|null} the nearest Rect. */ getNeighbor(dir, rects, wrap = true) { // Since we can only move into 1 direction at a time, we just need // to check 1 axis / property of the rects per movement (...almost). // An example probably makes this clearer. If we want to get the // neighbor in the N direction, we just look at the y's of the rects. // More specifically, we look for the y2's ('cmprProp') of the other // rects which are bigger than the y1 ('startProp') of `this`. The // nearest neighbor has y2 == this.y1. i. e. the neighbor and `this` // share a border. There may be multiple windows with the same distance. // In our example it might happen, if 2 windows are tiled side by side // bordering `this`. In that case we choose the window, which is the // nearest on the non-compared axis ('nonCmprProp'). The x property // in the this example. let startProp, cmprProp, nonCmprProp; if (dir === Direction.N) [startProp, cmprProp, nonCmprProp] = ['y', 'y2', 'x']; else if (dir === Direction.S) [startProp, cmprProp, nonCmprProp] = ['y2', 'y', 'x']; else if (dir === Direction.W) [startProp, cmprProp, nonCmprProp] = ['x', 'x2', 'y']; else if (dir === Direction.E) [startProp, cmprProp, nonCmprProp] = ['x2', 'x', 'y']; // Put rects into a Map with their relevenat pos'es as the keys and // filter out `this`. const posMap = rects.reduce((map, rect) => { if (rect.equal(this)) return map; const pos = rect[cmprProp]; if (!map.has(pos)) map.set(pos, []); map.get(pos).push(rect); return map; }, new Map()); // Sort the pos'es in an ascending / descending order. const goForward = [Direction.S, Direction.E].includes(dir); const sortedPoses = [...posMap.keys()].sort((a, b) => goForward ? a - b : b - a); const neighborPos = goForward ? sortedPoses.find(pos => pos >= this[startProp]) : sortedPoses.find(pos => pos <= this[startProp]); if (!neighborPos && !wrap) return null; // Since the sortedPoses array is in descending order when 'going // backwards', we always wrap by getting the 0-th item, if there // is no actual neighbor. const neighbors = posMap.get(neighborPos ?? sortedPoses[0]); return neighbors.reduce((currNearest, rect) => { return Math.abs(currNearest[nonCmprProp] - this[nonCmprProp]) <= Math.abs(rect[nonCmprProp] - this[nonCmprProp]) ? currNearest : rect; }); } /** * Gets the rectangle at `index`, if `this` is split into equally * sized rects. This function is meant to prevent rounding errors. * Rounding errors may lead to rects not aligning properly and thus * messing up other calculations etc... This solution may lead to the * last rect's size being off by a few pixels compared to the other * rects, if we split `this` multiple times. * * @param {number} index the position of the rectangle we want after * splitting this rectangle. * @param {number} unitSize the size of 1 partial unit of the rectangle. * @param {Orientation} orientation determines the split orientation * (horizontally or vertically). * @returns {Rect} the rectangle at `index` after the split. */ getUnitAt(index, unitSize, orientation) { unitSize = Math.floor(unitSize); const isVertical = orientation === Orientation.V; const lastIndex = Math.round(this[isVertical ? 'width' : 'height'] / unitSize) - 1; const getLastRect = () => { const margin = unitSize * index; return new Rect( isVertical ? this.x + margin : this.x, isVertical ? this.y : this.y + margin, isVertical ? this.width - margin : this.width, isVertical ? this.height : this.height - margin ); }; const getNonLastRect = (remainingRect, idx) => { const firstUnitRect = new Rect( remainingRect.x, remainingRect.y, isVertical ? unitSize : remainingRect.width, isVertical ? remainingRect.height : unitSize ); if (idx <= 0) { return firstUnitRect; } else { const remaining = remainingRect.minus(firstUnitRect)[0]; return getNonLastRect(remaining, idx - 1); } }; if (index === lastIndex) return getLastRect(); else return getNonLastRect(this, index); } /** * @param {Rect} rect * @returns {boolean} */ horizOverlap(rect) { rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; return this._rect.horiz_overlap(rect); } /** * @param {Rect} rect * @returns {[boolean, Rect]} */ intersect(rect) { rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; const [ok, intersection] = this._rect.intersect(rect); return [ok, new Rect(intersection)]; } /** * Get the Rects that remain from `this`, if `r` is cut off from it. * * @param {Rect|Rect[]} r either a single Rect or an array of Rects. * @returns {Rect[]} an array of Rects. */ minus(r) { return Array.isArray(r) ? this._minusRectArray(r) : this._minusRect(r); } /** * Gets the Rects, which remain from `this` after `rect` was cut off * / subtracted from it. * * Original idea from: \ * https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Rectangle_difference \ * No license is given except the general CC-BY-AS (for text) mentioned * in the footer. Since the algorithm seems fairly generic (just a few * additions / substractions), I think I should be good regardless... * I've modified the algorithm to make the left / right result rects bigger * instead of the top / bottom rects since screens usually have horizontal * orientations; so having the vertical rects take priority makes more sense. * * @param {Rect} rect the Rect to cut off from `this`. * @returns {Rect[]} an array of Rects. It contains 0 - 4 rects. */ _minusRect(rect) { rect = rect instanceof Mtk.Rectangle ? new Rect(rect) : rect; if (rect.containsRect(this)) return []; const [intersect] = this.intersect(rect); if (!intersect) return [this.copy()]; const resultRects = []; // Left rect const leftRectWidth = rect.x - this.x; if (leftRectWidth > 0 && this.height > 0) resultRects.push(new Rect(this.x, this.y, leftRectWidth, this.height)); // Right rect const rightRectWidth = this.x2 - rect.x2; if (rightRectWidth > 0 && this.height > 0) resultRects.push(new Rect(rect.x2, this.y, rightRectWidth, this.height)); const vertRectsX1 = rect.x > this.x ? rect.x : this.x; const vertRectsX2 = rect.x2 < this.x2 ? rect.x2 : this.x2; const vertRectsWidth = vertRectsX2 - vertRectsX1; // Top rect const topRectHeight = rect.y - this.y; if (topRectHeight > 0 && vertRectsWidth > 0) resultRects.push(new Rect(vertRectsX1, this.y, vertRectsWidth, topRectHeight)); // Bottom rect const bottomRectHeight = this.y2 - rect.y2; if (bottomRectHeight > 0 && vertRectsWidth > 0) resultRects.push(new Rect(vertRectsX1, rect.y2, vertRectsWidth, bottomRectHeight)); return resultRects; } /** * Gets the Rects that remain from `this`, if a list of rects is cut * off from it. * * @param {Rect[]} rects the list of Rects to cut off from `this`. * @returns {Rect[]} an array of the remaining Rects. */ _minusRectArray(rects) { if (!rects.length) return [this.copy()]; // First cut off all rects individually from `this`. The result is an // array of leftover rects (which are arrays themselves) from `this`. const individualLeftOvers = rects.map(r => this.minus(r)); // Get the final result by intersecting all leftover rects. return individualLeftOvers.reduce((result, currLeftOvers) => { const intersections = []; for (const leftOver of currLeftOvers) { for (const currFreeRect of result) { const [ok, inters] = currFreeRect.intersect(leftOver); ok && intersections.push(new Rect(inters)); } } return intersections; }); } /** * @param {Rect} rect * @returns {boolean} */ overlap(rect) { rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; return this._rect.overlap(rect); } /** * Makes `this` stick to `rect`, if they are close to each other. Use it * as a last resort to prevent rounding errors, if you can't use minus() * or getUnitAt(). * * @param {Rect} rect the rectangle to align `this` with. * @param {number} margin only align, if `this` and the `rect` are at most * this far away. * @returns {Rect} a reference to this. */ tryAlignWith(rect, margin = 4) { rect = rect instanceof Mtk.Rectangle ? new Rect(rect) : rect; const equalApprox = (value1, value2) => Math.abs(value1 - value2) <= margin; if (equalApprox(rect.x, this.x)) this.x = rect.x; else if (equalApprox(rect.x2, this.x)) this.x = rect.x2; if (equalApprox(rect.y, this.y)) this.y = rect.y; else if (equalApprox(rect.y2, this.y)) this.y = rect.y2; if (equalApprox(rect.x, this.x2)) this.width = rect.x - this.x; else if (equalApprox(rect.x2, this.x2)) this.width = rect.x2 - this.x; if (equalApprox(rect.y, this.y2)) this.height = rect.y - this.y; else if (equalApprox(rect.y2, this.y2)) this.height = rect.y2 - this.y; return this; } /** * @param {Rect} rect * @returns {Rect} */ union(rect) { rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; return new Rect(this._rect.union(rect)); } /** * @param {Rect} rect * @returns {boolean} */ vertOverlap(rect) { rect = rect instanceof Mtk.Rectangle ? rect : rect.meta; return this._rect.vert_overlap(rect); } /** * Getters */ get meta() { return this._rect.copy(); } get area() { return this._rect.area(); } get x() { return this._rect.x; } get x2() { return this._rect.x + this._rect.width; } get y() { return this._rect.y; } get y2() { return this._rect.y + this._rect.height; } get center() { return { x: this.x + Math.floor(this.width / 2), y: this.y + Math.floor(this.height / 2) }; } get width() { return this._rect.width; } get height() { return this._rect.height; } /** * Setters */ set x(value) { this._rect.x = Math.floor(value); } set x2(value) { this._rect.width = Math.floor(value) - this.x; } set y(value) { this._rect.y = Math.floor(value); } set y2(value) { this._rect.height = Math.floor(value) - this.y; } set width(value) { this._rect.width = Math.floor(value); } set height(value) { this._rect.height = Math.floor(value); } } Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/layouts_example.json000066400000000000000000000051451457776040200300760ustar00rootroot00000000000000[ { "_name": "Master and Stack [V]", "_items": [ { "rect": { "x": 0, "y": 0, "width": 0.5, "height": 1 }, "appId": null, "loopType": null }, { "rect": { "x": 0.5, "y": 0, "width": 0.5, "height": 1 }, "appId": null, "loopType": "h" } ] }, { "_name": "N-Columns", "_items": [ { "rect": { "x": 0, "y": 0, "width": 1, "height": 1 }, "appId": null, "loopType": "v" } ] }, { "_name": "2 : 1 [V]", "_items": [ { "rect": { "x": 0, "y": 0, "width": 0.66, "height": 1 }, "appId": null, "loopType": null }, { "rect": { "x": 0.66, "y": 0, "width": 0.34, "height": 1 }, "appId": null, "loopType": null } ] }, { "_name": "4 Quarters", "_items": [ { "rect": { "x": 0, "y": 0, "width": 0.5, "height": 0.5 }, "appId": null, "loopType": null }, { "rect": { "x": 0.5, "y": 0, "width": 0.5, "height": 0.5 }, "appId": null, "loopType": null }, { "rect": { "x": 0, "y": 0.5, "width": 0.5, "height": 0.5 }, "appId": null, "loopType": null }, { "rect": { "x": 0.5, "y": 0.5, "width": 0.5, "height": 0.5 }, "appId": null, "loopType": null } ] } ]Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/prefs/000077500000000000000000000000001457776040200251025ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/prefs/layoutRow.js000066400000000000000000000174101457776040200274500ustar00rootroot00000000000000import { Gdk, Gtk, GObject } from '../dependencies/prefs/gi.js'; import { _ } from '../dependencies/prefs.js'; import { Layout } from '../common.js'; import { LayoutRowEntry } from './layoutRowEntry.js'; /** * 1 LayoutRow represents 1 Layout in the preference window. It's just instanced * by layoutsPrefs.js (see that file for more details and general information * about layouts). 1 LayoutRow has a bunch of LayoutRowEntries, which each * represent a LayoutItem. A LayoutItem is a simple JS Object and has a * { rect, appId, loopType }. The rect is mandatory, the rest not. */ export const LayoutRow = GObject.registerClass({ GTypeName: 'TilingLayoutRow', Template: import.meta.url.replace(/prefs\/(.*)\.js$/, 'ui/$1.ui'), InternalChildren: [ 'addRowEntryButton', 'deleteButton', 'drawingArea', 'entryBox', 'errorLabel', 'expanderButton', 'nameEntry', 'rectCountLabel', 'shortcut', 'revealer' ], Signals: { 'changed': { param_types: [GObject.TYPE_BOOLEAN] } } }, class TilingLayoutRow extends Gtk.ListBoxRow { // Use a static variable to make sure the indices are unique since just using // something like the child index isn't enough because the user may add *and* // delete rows at random... so 1 child index may appear multiple times static instanceCount = 0; /** * @returns {number} the number of created LayoutRows since the last time * the layouts were loaded into the preference window. */ static getInstanceCount() { return TilingLayoutRow.instanceCount; } static resetInstanceCount() { TilingLayoutRow.instanceCount = 0; } /** * @param {{_name: string, _items: {rect: object, appId: ?string, loopType: ?string}[] * }|null} layout a parsed JS object representing a layout from the * layouts.json file. */ _init(layout, settings) { super._init(); this._settings = settings; this._layout = new Layout(layout); this._idx = TilingLayoutRow.instanceCount++; this._shortcutKey = `activate-layout${this._idx}`; // Initialize shortcut and its clear-button this._shortcut.initialize(this._shortcutKey, this._settings); // Set name. Don't use a placeholder, if there is one because of a bug // when reloading the layouts const name = this._layout.getName(); this._nameEntry.get_buffer().set_text(name, -1); this._nameEntry.set_placeholder_text(name ? '' : 'Nameless Layout...'); // Load the entries with values from the layout const items = this._layout.getItems(); items.forEach((item, idx) => { const rowEntry = new LayoutRowEntry(idx, item); rowEntry.connect('changed', this._onRowEntryChanged.bind(this)); this._entryBox.append(rowEntry); }); // Show the nr of rects for a quicker overview. this._rectCountLabel.set_label(items.length ? `(${items.length})` : ''); // Add one empty entry row this._onAddRowEntryButtonClicked(); // Update the preview / show the errorLabel this._updatePreview(); } destroy() { this.get_parent().remove(this); } activate() { this._nameEntry.grab_focus(); } /** * toggles whether the layout's rects are visible. */ toggleReveal() { this._revealer.reveal_child = !this._revealer.reveal_child; } /** * @returns {number} the index of this layout. */ getIdx() { return this._idx; } /** * @returns {{_name: string, _items: {rect: object, appId: ?string, loopType: ?string}[] * }|null} the layout object represented by this row. */ getLayout() { // First, filter out empty rows (i. e. rows without valid rects) this._layout.setItems(this._layout.getItems()); // Then, remove problematic items, if the rects have problems. E. g., // they may overlap each other, extend outside of the screen etc... // This is irreversible but fine since this function is only called // when the user presses the save button. Before that there will be // error messages shown in the preview area. let [ok, , idx] = this._layout.validate(); while (this._layout.getItemCount() && !ok) { this._layout.removeItem(idx); [ok, , idx] = this._layout.validate(); } return this._layout.getItemCount() ? this._layout : null; } /** * @returns {[boolean, string]} whether the preview was successful and a * potential error message. */ _updatePreview() { const [ok, errMsg] = this._layout.validate(); if (!ok) { // Print error in the preview area this._errorLabel.set_label(errMsg); this._drawingArea.set_draw_func(() => {}); } else { // Draw the actual preview for the rects this._errorLabel.set_label(''); this._drawingArea.set_draw_func((drawingArea, cr) => { const color = new Gdk.RGBA(); const width = drawingArea.get_allocated_width(); const height = drawingArea.get_allocated_height(); cr.setLineWidth(1.0); this._layout.getItems().forEach(item => { // Rects are in a slightly transparent white with a 1px outline // and a 5px gap between the different rects const rect = item.rect; color.parse('rgba(255, 255, 255, .2)'); Gdk.cairo_set_source_rgba(cr, color); cr.moveTo(rect.x * width + 5, rect.y * height + 5); cr.lineTo((rect.x + rect.width) * width - 5, rect.y * height + 5); cr.lineTo((rect.x + rect.width) * width - 5, (rect.y + rect.height) * height - 5); cr.lineTo(rect.x * width + 5, (rect.y + rect.height) * height - 5); cr.lineTo(rect.x * width + 5, rect.y * height + 5); cr.strokePreserve(); // Fill the rects in transparent black. // If the rect is a 'loop', lower the transparency. color.parse(`rgba(0, 0, 0, ${item.loopType ? .1 : .3})`); Gdk.cairo_set_source_rgba(cr, color); cr.fill(); }); cr.$dispose(); }); } this._drawingArea.queue_draw(); return [ok, errMsg]; } _onNameEntryChanged() { const name = this._nameEntry.get_buffer().get_text(); this._nameEntry.set_tooltip_text(name); this._layout.setName(name); const [ok] = this._layout.validate(); this.emit('changed', ok); } _onDeleteButtonClicked() { this._settings.set_strv(this._shortcutKey, []); this.emit('changed', true); this.destroy(); } _onExpanderButtonClicked() { this.toggleReveal(); } _onClearShortcutButtonClicked() { this._settings.set_strv(`activate-layout${this._idx}`, []); } _onAddRowEntryButtonClicked() { const rowEntry = new LayoutRowEntry(this._layout.getItemCount(), this._layout.addItem()); rowEntry.connect('changed', this._onRowEntryChanged.bind(this)); this._entryBox.append(rowEntry); } _onRowEntryChanged(entry, ok) { // ok only is about the change being ok for the *individual* entry // i. e. whether their format is correct if (!ok) { this.emit('changed', ok); return; } // allOk is about whether the guiEntries are also valid as a whole const [allOk] = this._updatePreview(); this.emit('changed', allOk); } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js000066400000000000000000000103361457776040200304720ustar00rootroot00000000000000import { Gio, Gtk, GObject } from '../dependencies/prefs/gi.js'; import { _ } from '../dependencies/prefs.js'; /** * Multiple LayoutRowEntries make up a LayoutRow.js. See that file for more info. */ export const LayoutRowEntry = GObject.registerClass({ GTypeName: 'TilingLayoutRowEntry', Template: import.meta.url.replace(/prefs\/(.*)\.js$/, 'ui/$1.ui'), InternalChildren: [ 'rectEntry', 'rectLabel', 'rectAppButton' ], Signals: { 'changed': { param_types: [GObject.TYPE_BOOLEAN] } } }, class TilingLayoutRowEntry extends Gtk.Box { _init(idx, item) { super._init({ orientation: Gtk.Orientation.HORIZONTAL, spacing: 8 }); this._item = item; this._rectLabel.set_label(`Rect ${idx}`); const loop = item.loopType ? `--${item.loopType}` : ''; const rect = item.rect; const text = Object.keys(rect).length !== 0 ? `${rect.x}--${rect.y}--${rect.width}--${rect.height}${loop}` : ''; this._rectEntry.get_buffer().set_text(text, -1); // Show a placeholder on the first entry, if it's empty if (!text) { if (idx === 0) { const placeholder = _("'User Guide' for help..."); this._rectEntry.set_placeholder_text(placeholder); } else { this._rectEntry.set_placeholder_text('x--y--width--height[--h|v]'); } } const appInfo = item.appId && Gio.DesktopAppInfo.new(item.appId); const iconName = appInfo?.get_icon().to_string() ?? 'list-add-symbolic'; this._rectAppButton.set_icon_name(iconName); } /** * @param {Gtk.Button} appButton src of the event. */ _onAppButtonClicked() { // Reset app button, if it already has an app attached if (this._item.appId) { this._rectAppButton.set_icon_name('list-add-symbolic'); this._item.appId = null; this.emit('changed', true); // Attach app to the button } else { const chooserDialog = new Gtk.AppChooserDialog({ modal: true }); chooserDialog.get_widget().set({ show_all: true, show_other: true }); chooserDialog.connect('response', (dlg, id) => { if (id === Gtk.ResponseType.OK) { const appInfo = chooserDialog.get_widget().get_app_info(); const iconName = appInfo.get_icon().to_string(); this._rectAppButton.set_icon_name(iconName); this._item.appId = appInfo.get_id(); this.emit('changed', true); } chooserDialog.destroy(); }); chooserDialog.show(); } } /** * @param {Gtk.Entry} entry src of the event. */ _onRectEntryChanged(entry) { const text = entry.get_buffer().get_text(); const [ok] = this._validateFormat(text); if (ok) { const values = text.split('--'); this._item.rect = { x: parseFloat(values[0].trim()), y: parseFloat(values[1].trim()), width: parseFloat(values[2].trim()), height: parseFloat(values[3].trim()) }; this._item.loopType = values[4] || null; } else { this._item.rect = {}; this._item.loopType = null; } this.emit('changed', ok); } /** * Validates whether `text` follows the format \ * 'Float--Float--Float--Float[--String]' * * @param {string} text * @returns {[boolean, string]} whether the `text` is valid and a * potential error message. */ _validateFormat(text) { const values = text.split('--'); // 4 -> x, y, width, height; 5 -> additionally, a loopType if (values.length < 4 || values.length > 5) return [false, 'Wrong format: invalid count.']; const notJustNrs = ['x', 'y', 'width', 'height'].some((p, idx) => { return Number.isNaN(parseFloat(values[idx].trim())); }); return notJustNrs ? [false, 'Wrong format: only numbers are allowed.'] : [true, '']; } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/prefs/layoutsPrefs.js000066400000000000000000000224731457776040200301500ustar00rootroot00000000000000import { Gio, GLib } from '../dependencies/prefs/gi.js'; import { LayoutRow } from './layoutRow.js'; /** * This class takes care of everything related to layouts (at least on the * preference side). It's only being instanced by prefs.js. After that, it * loads / saves layouts from / to the disk and loads the gui for managing * layouts. The gui is created by instancing a bunch of Gtk.ListBoxRows from * layoutGui.js for each layout and putting them into a Gtk.ListBox from the * prefs.ui file. * * A popup layout has a name (String) and an array of LayoutItems (JS Objects). * A LayoutItem has a rect (JS Objects), an optional (String) appId and optional * loopType (String). Only the rect is a mandatory. The name lets the user * search for a layout with the 'Search popup layout' keybinding. The rectangle's * properties range from 0 to 1 (-> relative scale to the monitor). After a layout * is activated by the user, the 'Tiling Popup' will appear at every LayoutItem's * rect and ask the user which of the open windows they want to tile to that rect. * If a loopType is set, the Tiling Popup will keep spawning at that spot and * all tiled windows will evenly share that rect until the user cancels the tiling * popup. Only then will we jump to the next LayoutItem. Possible loopTypes: * horizontal ('h') or vertical (any other non-empty string). This allows the * user to create 'Master and Stack' type of layouts. If an appId is defined, * instead of the Tiling Popup appearing, a new instance of the app will be * opened and tiled to that rect (or at least I tried to do that). * * By default, the settings for layouts are hidden behind the 'Advanced / * Experimental' switch because I used a lot of hacks / assumptions... and * I am not even using the layouts myself. However, I don't want to remove * an existing feature... thus it's hidden */ export default class { constructor(settings, builder, path) { // Keep a reference to the settings for the shortcuts this._settings = settings; // The Gtk.ListBox, which LayoutRows are added to this._layoutsListBox = builder.get_object('layouts_listbox'); // Unique button to save changes made to all layouts to the disk. For // simplicity, reload from file after saving to get rid of invalid input. this._saveLayoutsButton = builder.get_object('save_layouts_button'); this._saveLayoutsButton.connect('clicked', () => { this._saveLayouts(); this._loadLayouts(); }); // Unique button to load layouts from the disk // (discarding all tmp changes) without any user prompt this._reloadLayoutsButton = builder.get_object('reload_layouts_button'); this._reloadLayoutsButton.connect('clicked', () => { this._loadLayouts(); }); // Unique button to add a new *tmp* LayoutRow this._addLayoutButton = builder.get_object('add_layout_button'); this._addLayoutButton.connect('clicked', () => { const row = this._createLayoutRow(LayoutRow.getInstanceCount()); row.toggleReveal(); }); // Bind the general layouts keyboard shortcuts. ['search-popup-layout'].forEach(key => { const shortcut = builder.get_object(key.replaceAll('-', '_')); shortcut.initialize(key, this._settings); }); // Finally, load the existing settings. this._loadLayouts(path); } _loadLayouts(path) { this._applySaveButtonStyle(''); this._forEachLayoutRow(row => row.destroy()); LayoutRow.resetInstanceCount(); // Try to load layouts file. const saveFile = this._makeFile(); const [success, contents] = saveFile.load_contents(null); if (!success) return; let layouts = []; // Custom layouts are already defined in the file. if (contents.length) { layouts = JSON.parse(new TextDecoder().decode(contents)); // Ensure at least 1 empty row otherwise the listbox won't have // a height but a weird looking shadow only. layouts.length ? layouts.forEach((layout, idx) => this._createLayoutRow(idx, layout)) : this._createLayoutRow(0); // Otherwise import the examples... but only do it once! // Use a setting as a flag. } else { const importExamples = 'import-layout-examples'; if (!this._settings.get_boolean(importExamples)) return; this._settings.set_boolean(importExamples, false); const exampleFile = this._makeFile(`${path}/src`, 'layouts_example.json'); const [succ, c] = exampleFile.load_contents(null); if (!succ) return; layouts = c.length ? JSON.parse(new TextDecoder().decode(c)) : []; layouts.forEach((layout, idx) => this._createLayoutRow(idx, layout)); this._saveLayouts(); } } _saveLayouts() { this._applySaveButtonStyle(''); const layouts = []; this._forEachLayoutRow(layoutRow => { const lay = layoutRow.getLayout(); if (lay) { layouts.push(lay); // Check, if all layoutRows were valid so far. Use getIdx() // instead of forEach's idx because a layoutRow may have been // deleted by the user. if (layoutRow.getIdx() === layouts.length - 1) return; // Invalid or empty layouts are ignored. For example, the user // defined a valid layout with a keybinding on row idx 3 but left // the row at idx 2 empty. When saving, the layout at idx 2 gets // removed and layout at idx 3 takes its place (i. e. becomes // idx 2). We need to update the keybindings to reflect that. const keys = this._settings.get_strv(`activate-layout${layoutRow.getIdx()}`); this._settings.set_strv(`activate-layout${layouts.length - 1}`, keys); this._settings.set_strv(`activate-layout${layoutRow.getIdx()}`, []); } else { // Remove keyboard shortcuts, if they aren't assigned to a // valid layout, because they won't be visible to the user // since invalid layouts get removed this._settings.set_strv(`activate-layout${layoutRow.getIdx()}`, []); } }); const saveFile = this._makeFile(); saveFile.replace_contents( JSON.stringify(layouts), null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, null ); } /** * @param {string} [parentPath=''] path to the parent directory. * @param {string} [fileName=''] name of the layouts file. * @returns {object} the Gio.File. */ _makeFile(parentPath = '', fileName = '') { // Create directory structure, if it doesn't exist. const userConfigDir = GLib.get_user_config_dir(); const dirLocation = parentPath || GLib.build_filenamev([userConfigDir, '/tiling-assistant']); const parentDir = Gio.File.new_for_path(dirLocation); try { parentDir.make_directory_with_parents(null); } catch (e) {} // Create file, if it doesn't exist. const fName = fileName || 'layouts.json'; const filePath = GLib.build_filenamev([dirLocation, '/', fName]); const file = Gio.File.new_for_path(filePath); try { file.create(Gio.FileCreateFlags.NONE, null); } catch (e) {} return file; } /** * @param {string} [actionName=''] possible styles: 'suggested-action' * or 'destructive-action' */ _applySaveButtonStyle(actionName = '') { // The suggested-action is used to indicate that the user made // changes; the destructive-action, if saving will drop changes // (e. g. when changes were invalid) const actions = ['suggested-action', 'destructive-action']; const context = this._saveLayoutsButton.get_style_context(); actions.forEach(a => a === actionName ? context.add_class(a) : context.remove_class(a)); } /** * @param {number} index the index of the new layouts row. * @param {Layout} layout the parsed JS Object from the layouts file. */ _createLayoutRow(index, layout = null) { // Layouts are limited to 20 since there are only // that many keybindings in the schemas.xml file if (index >= 20) return; const layoutRow = new LayoutRow(layout, this._settings); layoutRow.connect('changed', (row, ok) => { // Un / Highlight the save button, if the user made in / valid changes. this._applySaveButtonStyle(ok ? 'suggested-action' : 'destructive-action'); }); this._layoutsListBox.append(layoutRow); return layoutRow; } _forEachLayoutRow(callback) { for (let i = 0, child = this._layoutsListBox.get_first_child(); !!child; i++) { // Get a ref to the next widget in case the curr widget // gets destroyed during the function call. const nxtSibling = child.get_next_sibling(); callback.call(this, child, i); child = nxtSibling; } } } Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/prefs/shortcutListener.js000066400000000000000000000162501457776040200310250ustar00rootroot00000000000000import { Adw, Gdk, GObject, Gtk } from '../dependencies/prefs/gi.js'; /** * A Widget to implement the shortcuts in the preference window. * It's an AdwActionRow, which contains a label showing the keybinding(s) * and a shortcut-clear-button. * * Some parts are from https://extensions.gnome.org/extension/2236/night-theme-switcher/. * _isBindingValid & _isKeyvalForbidden are straight up copied from its util.js * https://gitlab.com/rmnvgr/nightthemeswitcher-gnome-shell-extension/-/blob/main/src/utils.js */ export const ShortcutListener = GObject.registerClass({ GTypeName: 'ShortcutListener', Template: import.meta.url.replace(/prefs\/(.*)\.js$/, 'ui/$1.ui'), InternalChildren: ['keybindingLabel', 'clearButton', 'eventKeyController'], Properties: { keybinding: GObject.ParamSpec.string( 'keybinding', 'Keybinding', 'Key sequence', GObject.ParamFlags.READWRITE, null ) } }, class ShortcutListener extends Adw.ActionRow { /** * Only allow 1 active ShortcutListener at a time */ static isListening = false; static isAppendingShortcut = false; static listener = null; static listeningText = 'Press a shortcut...'; static appendingText = 'Append a new shortcut...'; /** * Starts listening for a keyboard shortcut. * * @param {ShortcutListener} shortcutListener the new active ShortcutListener */ static listen(shortcutListener) { if (shortcutListener === ShortcutListener.listener) return; ShortcutListener.stopListening(); shortcutListener.isActive = true; shortcutListener.setKeybindingLabel(ShortcutListener.listeningText); ShortcutListener.listener = shortcutListener; ShortcutListener.isListening = true; } /** * Stops listening for a keyboard shortcut. */ static stopListening() { if (!ShortcutListener.isListening) return; ShortcutListener.isListening = false; ShortcutListener.isAppendingShortcut = false; ShortcutListener.listener.isActive = false; ShortcutListener.listener.setKeybindingLabel(ShortcutListener.listener.getKeybindingLabel()); ShortcutListener.listener = null; } initialize(key, setting) { this._key = key; this._setting = setting; this.isActive = false; this.connect('realize', () => this.get_root().add_controller(this._eventKeyController)); this.keybinding = this._setting.get_strv(key) ?? []; } /* * Sets the label of the keybinding. */ setKeybindingLabel(label) { this._keybindingLabel.set_label(label); } /** * Gets the keybinding in a more pleasant to read format. * For example: [e,a] will become * 'Ctrl+Super+E / Super+A' or 'Disabled' * * @returns {string} */ getKeybindingLabel() { const kbLabel = this.keybinding.reduce((label, kb) => { const [, keyval, mask] = Gtk.accelerator_parse(kb); const l = Gtk.accelerator_get_label(keyval, mask); if (!label) return l; return l ? `${label} / ${l}` : label; }, ''); return kbLabel || 'Disabled'; } _onActivated() { this.isActive ? ShortcutListener.stopListening() : ShortcutListener.listen(this); } _onKeybindingChanged() { this._setting.set_strv(this._key, this.keybinding); this._clearButton.set_sensitive(this.keybinding.length); this.setKeybindingLabel(this.getKeybindingLabel()); } _onClearButtonClicked() { this.keybinding = []; ShortcutListener.stopListening(); } _onKeyPressed(eventControllerKey, keyval, keycode, state) { if (this !== ShortcutListener.listener) return Gdk.EVENT_PROPAGATE; let mask = state & Gtk.accelerator_get_default_mod_mask(); mask &= ~Gdk.ModifierType.LOCK_MASK; if (mask === 0) { switch (keyval) { case Gdk.KEY_BackSpace: this.keybinding = []; // falls through case Gdk.KEY_Escape: ShortcutListener.stopListening(); return Gdk.EVENT_STOP; case Gdk.KEY_KP_Enter: case Gdk.KEY_Return: case Gdk.KEY_space: ShortcutListener.isAppendingShortcut = !ShortcutListener.isAppendingShortcut; this.setKeybindingLabel(ShortcutListener.isAppendingShortcut ? ShortcutListener.appendingText : ShortcutListener.listeningText ); return Gdk.EVENT_STOP; } } if (!this._isBindingValid({ mask, keycode, keyval }) || !Gtk.accelerator_valid(keyval, mask)) return Gdk.EVENT_STOP; const sc = Gtk.accelerator_name_with_keycode(null, keyval, keycode, mask); this.keybinding = ShortcutListener.isAppendingShortcut ? [...this.keybinding, sc] : [sc]; ShortcutListener.stopListening(); return Gdk.EVENT_STOP; } /** * Checks, if the given key combo is a valid binding. * * @param {{mask: number, keycode: number, keyval:number}} combo An object * representing the key combo. * @returns {boolean} `true` if the key combo is a valid binding. */ _isBindingValid({ mask, keycode, keyval }) { if ((mask === 0 || mask === Gdk.SHIFT_MASK) && keycode !== 0) { if ( (keyval >= Gdk.KEY_a && keyval <= Gdk.KEY_z) || (keyval >= Gdk.KEY_A && keyval <= Gdk.KEY_Z) || (keyval >= Gdk.KEY_0 && keyval <= Gdk.KEY_9) || (keyval >= Gdk.KEY_kana_fullstop && keyval <= Gdk.KEY_semivoicedsound) || (keyval >= Gdk.KEY_Arabic_comma && keyval <= Gdk.KEY_Arabic_sukun) || (keyval >= Gdk.KEY_Serbian_dje && keyval <= Gdk.KEY_Cyrillic_HARDSIGN) || (keyval >= Gdk.KEY_Greek_ALPHAaccent && keyval <= Gdk.KEY_Greek_omega) || (keyval >= Gdk.KEY_hebrew_doublelowline && keyval <= Gdk.KEY_hebrew_taf) || (keyval >= Gdk.KEY_Thai_kokai && keyval <= Gdk.KEY_Thai_lekkao) || (keyval >= Gdk.KEY_Hangul_Kiyeog && keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) || (keyval === Gdk.KEY_space && mask === 0) || this._isKeyvalForbidden(keyval) ) return false; } return true; } /** * Checks, if the given keyval is forbidden. * * @param {number} keyval The keyval number. * @returns {boolean} `true` if the keyval is forbidden. */ _isKeyvalForbidden(keyval) { const forbiddenKeyvals = [ Gdk.KEY_Home, Gdk.KEY_Left, Gdk.KEY_Up, Gdk.KEY_Right, Gdk.KEY_Down, Gdk.KEY_Page_Up, Gdk.KEY_Page_Down, Gdk.KEY_End, Gdk.KEY_Tab, Gdk.KEY_KP_Enter, Gdk.KEY_Return, Gdk.KEY_Mode_switch ]; return forbiddenKeyvals.includes(keyval); } }); Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/ui/000077500000000000000000000000001457776040200244005ustar00rootroot00000000000000Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/ui/layoutRow.ui000066400000000000000000000135621457776040200267530ustar00rootroot00000000000000 Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/ui/layoutRowEntry.ui000066400000000000000000000026471457776040200277770ustar00rootroot00000000000000 Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/ui/prefs.ui000066400000000000000000001614301457776040200260630ustar00rootroot00000000000000
Report a Bug prefs.open-bug-report User Guide prefs.open-user-guide License prefs.open-license Changelog prefs.open-changelog Advanced... prefs.open-hidden-settings
info-menu dialog-information-symbolic General view-app-grid-symbolic Tiling Popup Open after tiling a window enable_tiling_popup center Include apps from all workspaces tiling_popup_all_workspace False center Tile Groups Disable Tile Groups Tiled windows will no longer adapt their size to other tiled windows nor be raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' and the Tiling Popup will also no longer work. disable_tile_groups center Raise together A tile group is created when a window gets tiled. If a tiled window is raised, raise the other windows of its tile group as well enable_raise_tile_group center App Switcher and Tiling Popup This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You may need to re-enable this or the other extension after toggling this setting tilegroups_in_app_switcher center Gaps Windows window_gap center 500 2 8 Screen Edges single_screen_gap center 500 2 8 Screen Edge Top screen_top_gap center 500 2 8 Screen Edge Left screen_left_gap center 500 2 8 Screen Edge Right screen_right_gap center 500 2 8 Screen Edge Bottom screen_bottom_gap center 500 2 8 Maximized Windows maximize_with_gap center Dynamic Keybinding Behavior The keybindings to maximize and tile to the top/bottom/left/right may change their behavior based on the window's tiling state Disabled Don't change the keybindings' behavior dynamic_keybinding_disabled_button Window Focus Switch focus to the tiled window in the direction of the pressed shortcut dynamic_keybinding_window_focus_button dynamic_keybinding_disabled_button Tiling State Adapt the tiling state to the pressed shortcut. For instance, a window tiled to the right half will tile to the bottom-right quarter, if 'tile to bottom' is activated dynamic_keybinding_tiling_state_button dynamic_keybinding_disabled_button Tiling State (Windows) Like 'Tiling State' but if the window isn't tiled or is already tiled to the bottom and the 'tile to bottom' shortcut is activated, minimize the window dynamic_keybinding_tiling_state_windows_button dynamic_keybinding_disabled_button Favorite Layout Move the window along your favorite Layout dynamic_keybinding_favorite_layout_button dynamic_keybinding_disabled_button Active Window Hint Disabled Don't indicate the focused window active_window_hint_disabled_button Minimal Temporarily indicate the focused window when switching to a workspace with multiple non-overlapping windows active_window_hint_minimal_button active_window_hint_disabled_button Always Always indicate the focused window unless it's maximized or in fullscreen. There are issues on Wayland with GTK4 popups active_window_hint_always_button active_window_hint_disabled_button Hint Color The color of the frame indicating the focused window active_window_hint_color_button center Border Size The border size of the frame indicating the focused window for the always active hint active_window_hint_border_size center 50 1 8 Inner Border Size The border for the always active hint reaching inside the window frame. This is meant to cover rounded corners. However, GTK4 popups on Wayland will put the window behind the hint for whatever reason... active_window_hint_inner_border_size center 50 1 8 Animations Tiling enable_tile_animations center Untiling enable_untile_animations center Default Window Movement Mode The movement mode that is activated when no modifier key is pressed Edge Tiling Moving the window to the screen edges or corners will open the default tile preview edge_tiling_checkbutton Adaptive Tiling Releasing the grab on a window while hovering over a tile will push the overlapped window(s) aside adaptive_tiling_checkbutton edge_tiling_checkbutton Favorite Layout The tile preview will stick to your favorite layout from the 'Layouts' page favorite_layout_checkbutton edge_tiling_checkbutton Ignore Tiling Assistant Use Edge Tiling without Tiling Assistant's features ignore_ta_checkbutton edge_tiling_checkbutton Other Monitor Switch Grace Period When a window is dragged to a new monitor the tile preview will stick to the old monitor for a very short time. This way you can tile windows by 'throwing' it towards any screen edge even if a monitor is bordering that edge. monitor_switch_grace_period center Low Performance Movement Mode Use this if there is a lag when moving windows around. This will however decrease the precision of the tile preview updates. low_performance_move_mode center Adapt 'Edge Tiling' to your Favorite Layout adapt_edge_tiling_to_favorite_layout center 'Adaptive Tiling' Move Mode Activator Disabled Ctrl Alt RMB Super 'Favorite Layout' Move Mode Activator Disabled Ctrl Alt RMB Super 'Ignore Tiling Assistant' Mode Activator Disabled Ctrl Alt RMB Super Vertical Edge Preview Trigger Area vertical_preview_area center 5 500 5 10 Horizontal Edge Preview Trigger Area horizontal_preview_area center 10 500 5 10 Inverse Top Screen Edge Action Timer toggle_maximize_tophalf_timer center 300 1500 50 10 Inverse Top Screen Edge Action for Landscape Displays enable_hold_maximize_inverse_landscape center Inverse Top Screen Edge Action for Portrait Displays enable_hold_maximize_inverse_portrait center Restore Window Size on Tiled windows may not properly restore their size on Wayland. If that's the case, use 'Restore Window Size on Grab End' Grab Start Grab End Keybindings preferences-desktop-keyboard-symbolic General Toggle 'Tiling Popup' Tile Editing Mode A keyboard-driven mode to manage your tiled windows Auto-Tile Un/tile the current window based on the visible tiles Toggle 'Always on Top' Toggle Maximization Toggle Vertical Maximization Toggle Horizontal Maximization Restore Window Size Move Window to Center Edge Tiling Tile to top Tile to bottom Tile to left Tile to right Corner Tiling Tile to top-left Tile to top-right Tile to bottom-left Tile to bottom-right Edge Tiling without Tiling Assistant Tile to top Tile to bottom Tile to left Tile to right Corner Tiling without Tiling Assistant Tile to top-left Tile to top-right Tile to bottom-left Tile to bottom-right Debugging Show Tiled Rects Show Free Screen Rects Layouts video-joined-displays-symbolic General Panel Indicator show_layout_panel_indicator center Search for a Layout Open a popup listing all the available layouts Layouts none center end 100 list-add-symbolic Add a new Layout. 100 media-floppy-symbolic Save the layouts to the disk. Invalid changes will be lost! 100 edit-undo-symbolic Reload the layouts from the disk - discarding all non-saved changes. go-previous-symbolic start start 6 6 center 1 12 vertical 96 dialog-warning-symbolic Advanced / Experimental Settings Show more settings in the main preference window enable_advanced_experimental_features center Tiling-Assistant-46/tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui000066400000000000000000000026231457776040200303230ustar00rootroot00000000000000 Tiling-Assistant-46/tiling-assistant@leleat-on-github/stylesheet.css000066400000000000000000000002451457776040200261000ustar00rootroot00000000000000.tiling-layout-search-highlight { background-color: rgba(255, 255, 255, 0.1); border-radius: 20px; } .layout-shortcut .boxed-list { box-shadow: none; } Tiling-Assistant-46/translations/000077500000000000000000000000001457776040200172375ustar00rootroot00000000000000Tiling-Assistant-46/translations/cs.po000066400000000000000000000506641457776040200202170ustar00rootroot00000000000000# Czech translations for PACKAGE package. # Copyright (C) 2021 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Vojtěch Perník , 2021. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2021-08-03 01:02+0200\n" "Last-Translator: Vojtěch Perník \n" "Language-Team: Czech \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "X-Generator: Poedit 2.4.3\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "Obecné" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Vyskakovací okno dlaždic" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Inverzní časovač akce horního okraje obrazovky" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Obnovit velikost okna na" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "začátku uchopení" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "konci uchopení" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Klávesové zkratky" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "Přepnout \"Vyskakovací okno dlaždic\"" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Režim úprav dlaždic" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Automatické dlaždice" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Přepnout maximalizaci" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Dlaždice nahoře" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Dlaždice dole" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Dlaždice vlevo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Dlaždice vpravo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Dlaždice nahoře vlevo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Dlaždice nahoře vpravo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Dlaždice dole vlevo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Dlaždice dole vpravo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "" #~ msgid "Raise Tile Groups together" #~ msgstr "Zvedání skupin dlaždic dohromady" #~ msgid "Window Gaps" #~ msgstr "Mezery mezi okny" #~ msgid "Gaps on Maximized Windows" #~ msgstr "Mezery kolem maximalizovaných oknen" #~ msgid "" #~ "This setting is intended for Wayland users. Tiled windows may not " #~ "properly restore their size when they are being grabbed on Wayland.\n" #~ "\n" #~ "If that is the case, you can try 'Restore Window Size on Grab End' " #~ "instead." #~ msgstr "" #~ "Toto nastavení je určeno pro uživatele systému Wayland. Dlaždicová okna " #~ "nemusí správně obnovit svou velikost, když jsou uchopována na Waylandu.\n" #~ "\n" #~ "V takovém případě můžete místo toho vyzkoušet \"Obnovit velikost okna na " #~ "konci uchopení\"." #~ msgid "Inverse Top Screen Edge Action:" #~ msgstr "Inverzní akce horního okraje obrazovky:" #~ msgid "Landscape Displays" #~ msgstr "Displeje na šířku" #~ msgid "Portrait Displays" #~ msgstr "Displeje na výšku" #~ msgid "" #~ "The focused window will try to fill the free screen space as good as " #~ "possible based on the tiled windows around it." #~ msgstr "" #~ "Zaměřené okno se bude snažit co nejlépe vyplnit volný prostor na " #~ "obrazovce na základě okolních oken s dlaždicemi." #~ msgid " General " #~ msgstr " Obecné " #~ msgid " Side Tiling " #~ msgstr " Dlaždice na straně " #~ msgid " Corner Tiling " #~ msgstr " Dlaždice v rohu " #~ msgid "Tiling Assistant" #~ msgstr "Asistent dlaždicování" #~ msgid "" #~ "If you want to report a bug or need help,\n" #~ "\n" #~ "please open an issue on Github." #~ msgstr "" #~ "Pokud chcete nahlásit chybu, nebo potřebujete pomoc,\n" #~ "\n" #~ "prosím vytvořte issue na GitHubu." #~ msgid "" #~ "The GUIDE offers a detailed explanation of every " #~ "feature." #~ msgstr "" #~ "GUIDE nabízí detailní vysvětlení každého nastavení a " #~ "funkce." #~ msgid "" #~ "The CHANGELOG lists the differences between each " #~ "extension version." #~ msgstr "" #~ "CHANGELOG obsahuje seznam změn provedené mezi " #~ "jednotlivými verzemi rozšíření." #~ msgid "" #~ "This extension is licensed under the GNU General Public License, version 2 " #~ "or later and comes with NO WARRANTY. A copy of this " #~ "license can be found in the Github repository." #~ msgstr "" #~ "Toto rozšíření je licencováno pod GNU General Public License, verze 2 " #~ "nebo novější a není dodáváno s ŽÁDNOU ZÁRUKOU. Kopii " #~ "této licence naleznete v repozitáři na GitHubu." #~ msgid "Help" #~ msgstr "Nápověda" #~ msgid "Hidden Settings" #~ msgstr "Skrytá nastavení" #~ msgid "Tiling Popup: Current Workspace only" #~ msgstr "Vyskakovací okno dlaždic: Pouze aktuální pracovní plocha" #~ msgid "Tile Editing Mode: Focus Color" #~ msgstr "Režim úpravy dlaždic: Barva zaměření" #~ msgid "Tile Animations" #~ msgstr "Animace dlaždicování" #~ msgid "Untile Animations" #~ msgstr "Animace zrušení dlaždicování" Tiling-Assistant-46/translations/de_CH.po000066400000000000000000000546611457776040200205550ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2022-03-19 12:06+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: de_CH\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.0.1\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "Einen Fehler melden" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "Benutzerhandbuch" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "Lizenz" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "Änderungsprotokoll" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "Fortgeschrittene..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "Allgemein" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Kachel Popup" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "Nach dem Kacheln eines Fensters öffnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "Anwendungen aus allen Arbeitsbereichen einbeziehen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "Kachel Gruppen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "Gemeinsam öffnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" "Eine Kachelgruppe wird erstellt, wenn ein Fenster gekachelt wird. Wenn ein " "gekacheltes Fenster geöffnet wird, werden auch die anderen Fenster der " "Kachelgruppe geöffnet" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "App Switcher und Kachel Popup" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" "Dies könnte zu Konflikten mit anderen App Switcher (auch bekannt als " "alt+Tab) Erweiterungen führen. Möglicherweise müssen Sie diese oder die " "andere Erweiterung wieder aktivieren, nachdem Sie diese Einstellung " "umgeschaltet haben" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "Lücken" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "Fenster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "Bildschirmränder" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "Maximierte Fenster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "Dynamisches Tastenbindungsverhalten" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "Deaktiviert" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "Fenster Fokus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "Kachelzustand" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "Kachelzustand (Windows)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" "Wie 'Kachelzustand', aber wenn das Fenster nicht gekachelt ist oder bereits " "bis zum unteren Rand gekachelt ist und die Tastenkombination 'bis zum " "unteren Rand kacheln' aktiviert ist, wird das Fenster minimiert" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "Bevorzugtes Layout" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "Verschieben Sie das Fenster entlang Ihres bevorzugten Layouts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "Animationen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "Kacheln" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "Entkacheln" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "Standard-Fensterbewegungsmodus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "Kacheln an den Rand" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" "Durch Verschieben des Fensters zu den Bildschirmrändern oder -ecken wird die " "Standardkachelvorschau geöffnet" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "Adaptive Kacheln" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" "Das Loslassen eines Fensters, während der Mauszeiger über einer Kachel " "schwebt, schiebt das überlappende Fenster zur Seite" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" "Die Kachelvorschau bleibt bei Ihrem bevorzugten Layout von der Seite " "'Layouts'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "'Kacheln an den Rand' an Ihr bevorzugtes Layout anpassen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "Aktivator für den Verschiebemodus 'Adaptive Kacheln'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "Strg" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "Alt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "RMB" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "Aktivator für den Verschiebemodus 'Favorisiertes Layout'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "Vertikale Randvorschau Auslösebereich" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "Horizontale Randvorschau Auslösebereich" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Umgekehrter Timer für die Aktion am oberen Bildschirmrand" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "Umgekehrter Timer für die Aktion eines querformatigen Displays" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "Umgekehrter Timer für die Aktion eines hochformatigen Displays" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Fenstergrösse wiederherstellen auf" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" "Bei gekachelten Fenstern kann es vorkommen, dass die Grösse auf Wayland " "nicht korrekt wiederhergestellt wird. Wenn das der Fall ist, verwenden Sie " "die Funktion 'Fenstergrösse am Greifende wiederherstellen'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "Greifen Start" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "Greifen Ende" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Tastenbindungen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "Umschalten 'Kacheln Popup'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Kachelbearbeitungsmodus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "Ein tastaturbasierter Modus zur Verwaltung Ihrer gekachelten Fenster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Auto-Kacheln" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "" "Entkacheln oder kacheln des aktuellen Fensters anhand der sichtbaren Kacheln" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "Umschalten 'Immer oben'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Umschalten Maximierung" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "Umschalten vertikale Maximierung" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "Umschalten horizontale Maximierung" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "Fenstergrösse wiederherstellen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "Fenster in die Mitte verschieben" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Kachel nach oben" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Kacheln nach unten" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Kacheln nach links" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Kacheln nach rechts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "Kacheln in die Ecke" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Kacheln nach oben links" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Kacheln nach oben rechts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Kacheln nach unten links" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Kacheln nach unten rechts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "Fehlersuche" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "Gekachelte Rechtecke anzeigen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "Freie Rechtecke anzeigen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "Layouts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "Panel Anzeige" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "Suche nach einem Layout" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "Öffnet ein Popup mit allen verfügbaren Layouts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "Ein neues Layout hinzufügen." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "" "Das Layout auf der Festplatte speichern. Ungültige Änderungen gehen verloren!" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" "Die Layouts werden von der Festplatte neu geladen, wobei alle nicht " "gespeicherten Änderungen verworfen werden." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "Erweiterte / Experimentelle Einstellungen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" "Ersetzen Sie die Tastenkombinationen. Drücken Sie die Leertaste oder die " "Eingabetaste, wenn Sie nach einer Tastenkombination suchen, um stattdessen " "eine neue an die vorhandenen Tastenkombinationen anzuhängen." #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "Tastenkombinationen löschen" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "Kachel Popup aktiviert" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "Kachel Popup wurde deaktiviert" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "Keine gültigen Layouts definiert." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "Popup Layouts: App nicht gefunden." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "Schreiben um zu suchen..." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "Unbenanntes Layout..." #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" "Der Kachelbearbeitungsmodus kann nicht aufgerufen werden, wenn kein " "Kachelfenster sichtbar ist." #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "'Benutzerhandbuch' für Hilfe..." #~ msgid "" #~ "The keyboard shortcuts to maximize and tile to the top, bottom, left, and " #~ "right won't change their behavior based on the window's tiling state" #~ msgstr "" #~ "Die Tastenkombinationen zum Maximieren und Kacheln nach oben, unten, " #~ "links und rechts ändern ihr Verhalten nicht mehr abhängig vom " #~ "Kachelzustand des Fensters" #~ msgid "" #~ "Switch focus to the tiled window in the direction of the pressed " #~ "shortcut, if there is one" #~ msgstr "" #~ "Den Fokus auf das gekachelte Fenster in Richtung der gedrückten " #~ "Tastenkombination umschalten, sofern eine solche vorhanden ist" #~ msgid "" #~ "Adapt the current window's tiling state to the pressed shortcut. For " #~ "instance, a window tiled to the right half will tile to the bottom-right " #~ "quarter, if 'tile to bottom' is activated" #~ msgstr "" #~ "Passt den Kachelzustand des aktuellen Fensters an das gedrückte " #~ "Tastenkürzel an. Zum Beispiel wird ein Fenster, das in der rechten Hälfte " #~ "gekachelt ist, in das rechte untere Viertel gekachelt, wenn 'Nach unten " #~ "kacheln' aktiviert ist" #~ msgid "Other Window Movement Settings" #~ msgstr "Weitere Einstellungen zur Fensterbewegung" #~ msgid "Show Changelog in Preferences after an Update" #~ msgstr "Changelog nach einem Update in den Voreinstellungen anzeigen" #~ msgid "Tiling Window Switcher" #~ msgstr "Kachel Fenster Umschalter" #~ msgid "Replace App Switcher" #~ msgstr "App Switcher ersetzen" #~ msgid "" #~ "Replace the App Switcher (a. k. a. Alt+Tab) with a window switcher, which " #~ "previews the windows and tile groups" #~ msgstr "" #~ "Ersetzen Sie den App Switcher (auch bekannt als Alt+Tab) durch einen " #~ "Fensterwechsler, der eine Vorschau der Fenster und Kachelgruppen zeigt" #~ msgid "Group Windows by App" #~ msgstr "Fenster nach Anwendung gruppieren" #~ msgid "" #~ "Windows of the same app are displayed as one item and can be cycled " #~ "through with the key above Tab" #~ msgstr "" #~ "Fenster der gleichen Anwendung werden als ein Element angezeigt und " #~ "können mit der Taste oberhalb von Tab durchgeblättert werden" #~ msgid "Hidden Settings" #~ msgstr "Versteckte Einstellungen" Tiling-Assistant-46/translations/de_DE.po000066400000000000000000000614611457776040200205470ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2022-04-24 12:06+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.0.1\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "Einen Fehler melden" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "Benutzerhandbuch" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "Lizenz" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "Änderungsprotokoll" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "Fortgeschrittene..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "Allgemein" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Kachel-Popup" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "Nach dem Zuordnen eines Fensters öffnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "Anwendungen aus allen Arbeitsbereichen einbeziehen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "Kachelgruppen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "Kachelgruppen deaktivieren" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" "Gekachelte Fenster passen ihre Größe nicht mehr an andere gekachelte Fenster " "an und werden nicht mehr gemeinsam vergrößert oder verändert.Die dynamische " "Tastenbindung 'Fensterfokus' und das Kachel-Popup funktionieren dann " "ebenfalls nicht mehr." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "Gemeinsam anheben" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" "Eine Kachelgruppe wird erstellt, wenn ein Fenster zugeordnet wird. Wenn ein " "zugeordnetes Fenster geöffnet wird, werden auch die anderen Fenster der " "Kachelgruppe geöffnet." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "App Switcher und Kachel-Popup" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" "Dies könnte zu Konflikten mit anderen App-Switcher-Erweiterungen (Alt+Tab) " "führen. Diese müssen möglicherweise erneut aktiviert werden, wenn diese " "Einstellung angeschaltet wurde." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "Zwischenraum" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "Fenster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "Bildschirmränder" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "Bildschirmrand oben" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "Bildschirmrand links" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "Bildschirmrand rechts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "Bildschirmrand unten" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "Maximierte Fenster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "Dynamisches Tastenbelegungsverhalten" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" "Die Tastenkombinationen zum Maximieren und Kacheln nach oben/unten/links/" "rechts können ihr Verhalten je nach Kachelzustand des Fensters ändern" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "Deaktiviert" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "Das Verhalten der Tastenkombinationen nicht ändern" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "Fenster-Fokus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" "Fokus auf das gekachelte Fenster in Richtung des angeklickten Shortcuts " "umschalten" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "Kachelzustand" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" "Passt den Kachelzustand an das gedrückte Tastenkürzel an. Beispielsweise " "wird ein zur rechten Hälfte gekacheltes Fenster zum rechten unteren Viertel " "gekachelt, wenn die Option 'Nach unten zuordnen' aktiviert ist. " #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "Kachelzustand (Windows)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" "Wie 'Kachelzustand', aber wenn das Fenster nicht zugeordnet ist oder bereits " "am unteren Rand angeordnet ist und die Tastenkombination 'Zum unteren Rand " "zuordnen' aktiviert ist, wird das Fenster minimiert." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "Favorisiertes Layout" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "Verschiebt das Fenster entlang des favorisierten Layouts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "Aktiver Fensterhinweis" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "Das fokussierte Fenster nicht anzeigen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "Minimal" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" "Vorübergehendes Anzeigen des fokussierten Fensters beim Wechsel zu einem " "Arbeitsbereich mit mehreren sich nicht überlappenden Fenstern" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "Immer" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" "Zeigt immer das fokussierte Fenster an, es sei denn, es ist maximiert oder " "im Vollbildmodus. Es gibt Probleme unter Wayland mit GTK4 Popups" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "Hinweisfarbe" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "Die Farbe des Rahmens, der das fokussierte Fenster anzeigt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "Rahmengröße" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" "Die Größe des Rahmens, der das fokussierte Fenster für den immer aktiven " "Hinweis anzeigt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "Innere Rahmengröße" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" "Die Umrandung des immer aktiven Hinweises reicht bis in den Fensterrahmen. " "Dies ist dazu gedacht, abgerundete Ecken abzudecken. Allerdings werden GTK4-" "Popups unter Wayland das Fenster aus irgendeinem Grund dahinter setzen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "Animationen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "Kacheln" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "Entkacheln" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "Standard-Fensterbewegungsmodus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "An den Rand zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" "Durch Verschieben des Fensters zu den Bildschirmrändern oder -ecken wird die " "Standardkachelvorschau geöffnet" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "Dynamisches Zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" "Das Loslassen eines Fensters, während der Mauszeiger über einer Kachel " "schwebt, schiebt das überlappende Fenster zur Seite" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" "Die Kachelvorschau bleibt bei Ihrem bevorzugten Layout von der Seite " "'Layouts'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "Kachelassistent ignorieren" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "Verwendung von Kantenkachelung ohne die Funktionen vom Kachelassistent" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "Andere" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "Monitorwechsel Wartezeit" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" "Wenn ein Fenster auf einen neuen Monitor gezogen wird, bleibt die " "Kachelvorschau für eine sehr kurze Zeit auf dem alten Monitor aktiv. Auf " "diese Weise können Sie Fenster kacheln, indem Sie sie auf eine beliebige " "Bildschirmkanten 'werfen', selbst wenn ein Monitor an diese Kante angrenzt." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "Bewegungsmodus mit geringer Leistung" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" "Verwenden Sie diese Funktion, wenn es beim Verschieben von Fenstern zu " "Verzögerungen kommt. Allerdings wird dadurch die Genauigkeit der " "Kachelvorschauaktualisierungen verringert." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "'An den Rand zuordnen' an Ihr bevorzugtes Layout anpassen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "Aktivator für den Verschiebemodus 'Dynamisches Zuordnen'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "Strg" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "Alt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "RMB" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "Super" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "Aktivator für den Verschiebemodus 'Favorisiertes Layout'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "'Ignoriere Kachel-Assistent' Modus Schalter " #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "Vertikale Randvorschau Auslösebereich" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "Horizontale Randvorschau Auslösebereich" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Umgekehrter Timer für die Aktion am oberen Bildschirmrand" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "Umgekehrter Timer für die Aktion eines querformatigen Displays" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "Umgekehrter Timer für die Aktion eines hochformatigen Displays" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Fenstergrösse wiederherstellen auf" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" "Bei zugeordneten Fenstern kann es vorkommen, dass die Grösse auf Wayland " "nicht korrekt wiederhergestellt wird. Wenn das der Fall ist, muss die " "Funktion 'Fenstergrösse am Greifende wiederherstellen' genutzt werden." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "Greifen Start" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "Greifen Ende" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Tastenbelegung" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "Umschalten 'Kacheln Popup'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Kachelbearbeitungsmodus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "Ein tastaturbasierter Modus zur Verwaltung der gekachelten Fenster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Auto-Zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "" "Zuordnen oder Trennen des aktuellen Fensters anhand der sichtbaren Kacheln" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "Umschalten 'Immer oben'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Umschalten Maximierung" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "Umschalten vertikale Maximierung" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "Umschalten horizontale Maximierung" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "Fenstergrösse wiederherstellen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "Fenster in die Mitte verschieben" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Nach oben zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Nach unten zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Nach links zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Nach rechts zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "In die Ecke zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Nach oben links zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Nach oben rechts zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Nach unten links zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Nach unten rechts zuordnen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "Kantenkachelung ohne Assistent" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "Eckenkachelung ohne Assistenz" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "Debugging" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "Gekachelte Rechtecke anzeigen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "Freie Rechtecke anzeigen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "Layouts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "Panel Anzeige" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "Suche nach einem Layout" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "Öffnet ein Popup mit allen verfügbaren Layouts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "Ein neues Layout hinzufügen." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "" "Das Layout auf der Festplatte speichern. Ungültige Änderungen gehen verloren!" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" "Die Layouts werden von der Festplatte neu geladen, wobei alle nicht " "gespeicherten Änderungen verworfen werden." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "Erweiterte / Experimentelle Einstellungen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "Weitere Einstellungen in den Hauptmenü anzeigen" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" "Ersetzen Sie die Tastenkombinationen. Drücken Sie die Leertaste oder die " "Eingabetaste, wenn Sie nach einer Tastenkombination suchen, um stattdessen " "eine neue an die vorhandenen Tastenkombinationen anzuhängen." #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "Tastenkombinationen löschen" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "Kachel Popup aktiviert" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "Kachel Popup wurde deaktiviert" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "Keine gültigen Layouts definiert." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "Popup Layouts: App nicht gefunden." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "Schreiben um zu suchen..." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "Unbenanntes Layout..." #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" "Der Kachelbearbeitungsmodus kann nicht aufgerufen werden, wenn kein " "Kachelfenster sichtbar ist." #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "'Benutzerhandbuch' für Hilfe..." #~ msgid "" #~ "The keyboard shortcuts to maximize and tile to the top, bottom, left, and " #~ "right won't change their behavior based on the window's tiling state" #~ msgstr "" #~ "Die Tastenkombinationen zum Maximieren und Zuordnen nach oben, unten, " #~ "links und rechts ändern ihr Verhalten nicht mehr abhängig vom Zustand des " #~ "Fensters" #~ msgid "" #~ "Switch focus to the tiled window in the direction of the pressed " #~ "shortcut, if there is one" #~ msgstr "" #~ "Den Fokus auf das angeordnete Fenster in Richtung der gedrückten " #~ "Tastenkombination umschalten, sofern eine Tastenkombination definiert ist" #~ msgid "" #~ "Adapt the current window's tiling state to the pressed shortcut. For " #~ "instance, a window tiled to the right half will tile to the bottom-right " #~ "quarter, if 'tile to bottom' is activated" #~ msgstr "" #~ "Passt den Kachelzustand des aktuellen Fensters an das gedrückte " #~ "Tastenkürzel an. Zum Beispiel wird ein Fenster, das in der rechten Hälfte " #~ "angeordnet ist, in das rechte untere Viertel verschoben, wenn 'Nach unten " #~ "zuordnen' aktiviert ist." #~ msgid "Other Window Movement Settings" #~ msgstr "Weitere Einstellungen zur Fensterbewegung" #~ msgid "Show Changelog in Preferences after an Update" #~ msgstr "Changelog in den Einstellungen nach einem Update anzeigen" #~ msgid "Tiling Window Switcher" #~ msgstr "Kachel-Fenster-Switcher" #~ msgid "Replace App Switcher" #~ msgstr "App Switcher ersetzen" #~ msgid "" #~ "Replace the App Switcher (a. k. a. Alt+Tab) with a window switcher, which " #~ "previews the windows and tile groups" #~ msgstr "" #~ "Ersetzt den App Switcher (Alt+Tab) durch einen Fenster-Switcher, der eine " #~ "Vorschau der Fenster und Kachelgruppen zeigt" #~ msgid "Group Windows by App" #~ msgstr "Fenster nach Anwendung gruppieren" #~ msgid "" #~ "Windows of the same app are displayed as one item and can be cycled " #~ "through with the key above Tab" #~ msgstr "" #~ "Fenster der gleichen Anwendung werden als ein Element angezeigt und " #~ "können mit der Taste oberhalb von Tab durchgeblättert werden" #~ msgid "Hidden Settings" #~ msgstr "Versteckte Einstellungen" Tiling-Assistant-46/translations/es.po000066400000000000000000000576171457776040200202260ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2022-12-03 18:38+0200\n" "Last-Translator: Sergio Varela \n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 42.0\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "Informar de un error" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "Guía de usuario" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "Licencia" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "Registro de cambios" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "Avanzado..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "General" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Ventana emergente de distribución en mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "Abrir después de disponer en mosaico una ventana" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "Incluir aplicaciones de todos los espacios de trabajo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "Grupos de ventanas en mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "Desactivar los grupos de mosaicos" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "Grupo en primer plano" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" "Se crea un grupo de ventanas cuando una ventana se dispone en mosaico . Si " "una de las ventanas del grupo pasa a primer plano, el resto también lo hacen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "" "Conmutador de aplicaciones y ventana emergente de disposición en mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" "Esto podría entrar en conflicto con otras extensiones de conmutación de " "aplicaciones (también conocidas como Alt+Tab). Es posible que tenga que " "reactivar esta o la otra extensión después de modificar esta configuración" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "Espaciado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "Ventanas" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "Bordes de pantalla" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "Borde de pantalla superior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "Borde de la pantalla izquierda" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "Borde de la pantalla derecha" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "Borde inferior de la pantalla" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "Ventanas maximizadas" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "Comportamiento dinámico de los atajos de teclado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "Desactivado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "No cambie el comportamiento de los enlaces de las teclas" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "Enfoque de ventana" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "Estado de disposición en mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "Estado de disposición en mosaico (Ventanas)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" "Igual que 'Estado de disposición en mosaico', con la diferencia de que si el " "atajo ''Disponer en mosaico en la parte inferior\" es activado y la ventana " "no está dispuesta en mosaico o lo está en la parte inferior, minimiza la " "ventana" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "Distribución favorita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "Mueve la ventana de acuerdo a tu distribución favorita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "Sugerencia de ventana activa" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "No indicar la ventana enfocada" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "Mínimo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "Siempre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "Color del indicio" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "El color del marco que indica la ventana enfocada" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "Tamaño de los bordes" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "Tamaño del borde interior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "Animaciones" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "Al disponer la ventana en mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "Al sacar la ventana del mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "Modo de movimiento de la ventana por defecto" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "Disposición en mosaico en los bordes de la pantalla" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" "Al mover la ventana a los bordes o esquinas de la pantalla se abrirá la " "vista previa de disposición en mosaico por defecto" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "Disposición en mosaico adaptativa" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" "Si se suelta una ventana mientras se pasa por encima de una ventana " "dispuesta en mosaico, se apartará la(s) ventana(s) superpuesta(s)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" "La vista previa de disposición en mosaico se ceñirá a tu distribución " "favorita de la página 'Distribuciones'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "Otro" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "" "Adaptar la 'Disposición en mosaico en el borde' a tu distibución favorita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "Activador del modo de movimiento 'Organización en mosaico adaptativa'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "Ctrl" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "Alt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "Botón derecho del ratón" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "Activador del modo de movimiento 'Distribución favorita'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "Área de activación de la vista previa del borde vertical" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "Área de activación de la vista previa del borde horizontal" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Tiempo hasta conmutar la acción del borde superior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "" "Acción en borde superior invertida para pantallas con disposición apaisada" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "" "Acción en borde superior invertida para pantallas con disposición vertical" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Restaurar el tamaño de la ventana" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" "Puede ocurrir que las ventanas en mosaico no restauraren correctamente su " "tamaño en Wayland. Si ese es el caso, utiliza 'Restaurar el tamaño de la " "ventana al soltar'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "al agarrar" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "al soltar" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Atajos de teclado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "Activar/desactivar la \"Ventana emergente de disposición en mosaico\"" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Modo de edición de disposición en mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "Un modo de manejo de las ventanas en mosaico mediante el teclado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Auto-organizar en mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "" "Disponer en mosaico o no la ventana actual en base a las ventanas en mosaico " "visibles" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "Activar/desactivar 'siempre encima'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Activar/desactivar el maximizado de la ventana" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "Activar/desactivar el maximizado vertical de la ventana" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "Activar/desactivar el maximizado horizontal de la ventana" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "Restaurar el tamaño de la ventana" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "Mover la ventana al centro" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Disponer en mosaico en el borde superior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Disponer en mosaico en el borde inferior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Disponer en mosaico en el borde izquierdo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Disponer en mosaico en el borde derecho" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "Disposición en mosaico en las esquinas de la pantalla" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Disponer en mosaico en la esquina superior izquierda" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Disponer en mosaico en la esquina superior derecha" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Disponer en mosaico en la esquina inferior izquierda" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Disponer en mosaico en la esquina inferior derecha" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "Depuración" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "Mostrar los rectángulos del mosaico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "Mostrar los rectángulos del espacio libre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "Distribuciones" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "Mostrar indicador en el panel" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "Buscar una distribución" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "" "Abre una ventana emergente con una lista de todas las distribuciones " "disponibles" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "Añadir una nueva distribución." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "" "Guardar las distribuciones en el disco. ¡Los cambios no válidos se perderán!" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" "Recargar las distribuciones desde el disco, descartando todos los cambios no " "guardados." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "Ajustes avanzados/experimentales" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" "Reemplazar los atajos de teclado. Pulsa 'espacio' o 'retorno' mientras se " "está grabando un atajo para añadir uno nuevo a los atajos existentes." #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "Borrar los atajos de teclado" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "Ventana emergente de disposición en mosaico habilitada" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "La ventana emergente de disposición en mosaico fue deshabilitada" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "No hay distribuciones válidas definidas." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "Ventana emergente de distribuciones: aplicación no encontrada." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "Escriba para buscar..." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "Distribución sin nombre..." #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" "No se puede activar el 'Modo de edición de distribución en mosaico' si no " "hay una ventana en mosaico visible." #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "Ver 'Guía de usuario' para obtener ayuda..." #~ msgid "" #~ "The keyboard shortcuts to maximize and tile to the top, bottom, left, and " #~ "right won't change their behavior based on the window's tiling state" #~ msgstr "" #~ "Los atajos de teclado para maximizar y posicionar la ventana en mosaico " #~ "en la parte superior, inferior, izquierda y derecha no cambiarán su " #~ "comportamiento en función de si la ventana está dispuesta en mosaico o no" #~ msgid "" #~ "Switch focus to the tiled window in the direction of the pressed " #~ "shortcut, if there is one" #~ msgstr "" #~ "Cambia el foco a la ventana en mosaico posicionada en la dirección del " #~ "acceso directo pulsado, si hay uno" #~ msgid "" #~ "Adapt the current window's tiling state to the pressed shortcut. For " #~ "instance, a window tiled to the right half will tile to the bottom-right " #~ "quarter, if 'tile to bottom' is activated" #~ msgstr "" #~ "Adapta el estado de disposición en mosaico de la ventana actual al atajo " #~ "pulsado. Por ejemplo, una ventana dispuesta en mosaico en la mitad " #~ "derecha se posicionará en el cuarto inferior derecho, si el atajo " #~ "\"Posicionar en mosaico en la parte inferior\" es activado" #~ msgid "Other Window Movement Settings" #~ msgstr "Otros ajustes del movimiento de ventanas" #~ msgid "Show Changelog in Preferences after an Update" #~ msgstr "" #~ "Mostrar el registro de cambios en las preferencias después de una " #~ "actualización" #~ msgid "Tiling Window Switcher" #~ msgstr "Conmutador de ventanas en mosaico" #~ msgid "Replace App Switcher" #~ msgstr "Reemplazar el conmutador de aplicaciones" #~ msgid "" #~ "Replace the App Switcher (a. k. a. Alt+Tab) with a window switcher, which " #~ "previews the windows and tile groups" #~ msgstr "" #~ "Reemplazar el conmutador de aplicaciones (también conocido como Alt+Tab) " #~ "por un conmutador de ventanas, que previsualiza las ventanas y los grupos " #~ "de ventanas en mosaico" #~ msgid "Group Windows by App" #~ msgstr "Agrupar ventanas por aplicación" #~ msgid "" #~ "Windows of the same app are displayed as one item and can be cycled " #~ "through with the key above Tab" #~ msgstr "" #~ "Las ventanas de una misma aplicación se muestran como un solo elemento y " #~ "se pueden recorrer con la tecla Tab" #~ msgid "Hidden Settings" #~ msgstr "Ajustes ocultos" Tiling-Assistant-46/translations/hu.po000066400000000000000000000555731457776040200202320ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2023-02-28 20:11+0100\n" "Last-Translator: infeeeee \n" "Language-Team: \n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.2.2\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "Hiba jelentése" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "Felhasználói dokumentáció" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "Licensz" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "Változásnapló" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "Speciális..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "Általános" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Csempéző felugró ablak" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "Megnyitás egy ablak csempézése után" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "Az összes munkaterületen szereplő ablak belevétele" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "Csempe csoportok" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "Csempe csoportok kikapcsolása" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" "Csempézett ablakok nem fognak alkalmazkodni más csempézett ablakokhoz, és " "nem fognak együtt sem előtérbe jönni, sem átméreteződni. A dinamikus " "gyorsbillentyű viselkedései közül az 'Ablak fókuszálása' és a Csempéző " "felugró ablak nem fog működni." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "Előtérbe hozás együtt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" "Egy csempe csoport jön létre, amikor ablakok csempézésekor. Ha egy " "csempézett ablak előtérbe kerül, akkor a csoport többi tagja is vele együtt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "Alkalmazásváltó és csempéző felugró ablak" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" "Összeütközhet más alkalmazásváltó (más néven Alt+Tab) kiterjesztésekkel. " "Ennek vagy a másik a kiterjesztésnek a ki-be kapcsolása lehet szükséges " "ennek a beállításnak a megváltoztatása után" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "Hézagok" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "Ablakok" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "Képernyő szélek" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "Képernyő felső széle" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "Képernyő bal széle" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "Képernyő jobb széle" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "Képernyő alsó széle" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "Maximalizált ablakok" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "Dinamikus gyorsbillentyűk viselkedése" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" "A gyorsbillentyűk az ablakok maximalizálásához és fel/le/jobbra/balra " "csempézéséhez az ablak csempézettségétől függően máshogy működhetnek" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "Kikapcsolva" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "A gyorsbillentyűk működése nem változik" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "Ablak fókuszálása" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "A leütött gyorsbillentyű irányában levő ablak fókuszálása" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "Csempézettség állapota" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" "A ablak csempézettség állapotától függ a gyorsbillentyű működése. Például, " "ha egy ablak a a képernyő jobb szélére van csempézve, akkor a képernyő jobb " "alsó sarkába fog ugrani a 'csempézés alulra' gyorsbillentyű használatakor" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "Csempézettség állapota (ablakok)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" "Mint a 'csempézettség állapota', de ha az ablak nincs csempézve, vagy már " "alulra van csempézve a 'csempézés alulra' gyorsbillentyű megnyomásakor az " "ablak minimalizálódni fog" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "Kedvenc elrendezés" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "Ablak mozgatása a kedvenc elrendezés mentén" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "Aktív ablak kiemelése" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "A fókuszált ablak megjelölésének kikapcsolása" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "Minimális" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" "A fókuszált ablak ideiglenesen megjelölése, több, egymást nem átfedő " "ablakkal rendelkező munkaterületre váltásakor" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "Mindig" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" "A fókuszált ablak megjelölése, hacsak nem maximalizált, vagy teljes " "képernyős. Problémák fordulhatnak elő Wayland és GTK4 felugró ablakokkal" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "Kiemelés színe" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "A fókuszált ablak kiemelésének a színe" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "Szegély mérete" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" "A fókuszált ablakot kiemelő keret szegélyének a mérete a mindig aktív " "kiemelésnél" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "Belső szegély mérete" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" "A mindig aktív kiemeléshez tartozó szegély az ablak keretén belül. El " "kellene takarnia a lekerekített sarkokat. Azonban GTK4 felugró ablakok " "Waylanden az ablakot a kiemelés mögött jelenítik meg valamiért..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "Animációk" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "Csempézés" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "Csempézés megszüntetése" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "Alapértelmezett ablak mozgatási mód" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "Szél csempézés" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" "A képernyő széléhez húzott ablak az alapértelmezett csempe előnézetet nyitja " "meg" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "Adaptív csempézés" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" "Ha az ablak egy csempe fölött lett elengedve, akkor odébb fogja tolni az " "átfedő ablakot, ablakokat" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" "A csempe előnézet csak a kedvenc elrendezést fogja használni az " "'Elrendezések' oldalról" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "Csempézési segéd mellőzése" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "Szél csempézés használata, a 'Tiling Assistant' funkciói nélkül" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "Egyéb" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "Monitorváltás türelmi ideje" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" "Egy ablak a új monitorra húzásakor, a csempe előnézet a régi monitorhoz fog " "ragadni egy nagyon rövid ideig. Így lehetséges az ablakok csempézése a " "képernyő széle felé való \"dobással\", még akkor is, ha egy másik monitor " "található azon az oldalon." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "Alacsony teljesítményű mozgatás mód" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" "Ablakok mozgatásakor jelentkező késleltetéskor ajánlott bekapcsolni. Azonban " "ez a mód az előnézetek frissítésének a pontosságát is csökkenti." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "A 'szél csempézés' alkalmazása a kedvenc elrendezéshez" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "'Adaptív csempézés' mozgatási mód aktiválója" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "Ctrl" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "Alt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "Jobbklikk" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "Szuper" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "'Kedvenc elrendezés' mozgatási mód aktiválója" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "'Csempézési segéd mellőzése' mód aktiválója" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "Függőleges szél előnézet aktiváló terület" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "Vízszintes szél előnézet aktiváló terület" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Fordított felső képernyő szél művelet időzítő" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "Fordított felső képernyő szél művelet fekvő kijelzőkhöz" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "Fordított felső képernyő szél művelet álló kijelzőkhöz" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Ablakok méretének visszaállítása ilyenkor" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" "Csempézett ablakok néha nem tudják megfelelően helyreállítani a méretüket " "Waylanden. Ezt az 'Megfogás végén' funkció kiválasztásával megoldható" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "Megfogás elején" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "Megfogás végén" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Gyorsbillentyűk" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "'Csempéző felugró ablak' be/ki" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Csempe szerkesztő mód" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "Billentyűzet vezérelt mód, a csempézett ablakok kezelésére" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Auto-csempézés" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "" "Az aktuális ablak csempézése, vagy csempézés megszüntetése a látható csempék " "alapján" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "'Mindig felül' be/ki" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Maximalizálás be/ki" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "Függőleges maximalizálás be/ki" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "Vízszintes maximalizálás be/ki" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "Ablak méretének visszaállítása" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "Ablak középre mozgatása" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Csempézés felülre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Csempézés alulra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Csempézés balra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Csempézés jobbra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "Sarok csempézés" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Csempézés bal felülre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Csempézés jobb felülre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Csempézés bal alulra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Csempézés jobb alulra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "Szél csempézés használata 'Tiling Assistant' nélkül" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "Sarok csempézés használata 'Tiling Assistant' nélkül" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "Hibakeresés" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "Csempézett téglalapok megjelenítése" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "Üres képernyő téglalapok megjelenítése" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "Elrendezések" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "Jelző a felső sávon" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "Elrendezés keresése" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "Felugró ablak megnyitása az elérhető elrendezések listájával" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "Új elrendezés hozzáadása." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "Elrendezés mentése a lemezre. Érvénytelen változások el fognak veszni!" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" "Elrendezések újratöltése a lemezről, az el nem mentett változások " "elvetésével." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "Speciális / Kísérleti beállítások" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "Több beállítás megjelenítése a beállítások ablakban" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" "Gyorsbillentyűk kicserélése. Gyorsbillentyűk megadásakor 'szóköz' vagy " "'enter' megnyomásával egy új gyorsbillentyű fűzése a meglévő mögé." #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "Gyorsbillentyűk eltávolítása" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "Csempéző felugró ablak bekapcsolva" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "Csempéző felugró ablak kikapcsolva" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "Nem található érvényes elrendezés." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "Felugró elrendezések: Alkalmazás nem található." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "Kereséshez kezdjen el gépelni..." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "Névtelen elrendezés..." #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" "Nem lehet a 'Csempe szerkesztő mód'-ba belépni, ha nincs egy ablak se " "csempézve." #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "Felhasználói dokumentáció segíthet..." Tiling-Assistant-46/translations/it_IT.po000066400000000000000000000620461457776040200206170ustar00rootroot00000000000000# Tiling-Assistant GNOME extension. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Andrea Brandi , 2022. # Albano Battistella , 2023. # msgid "" msgstr "" "Project-Id-Version: Tiling-Assistant\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2023-11-26 17:11+0100\n" "Last-Translator: Albano Battistella \n" "Language-Team: Italian <>\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "X-Generator: Gtranslator 40.0\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "Segnala un bug" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "Guida utente" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "Licenza" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "Registro modifiche" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "Avanzate..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "Generale" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Popup finestre affiancate" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "Apri quando una finestra viene affiancata" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "Includi app da tutte le aree di lavoro" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "Gruppi finestre affiancate" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "Disabilita i gruppi di finestre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" "Le finestre affiancate non adatteranno più le loro dimensioni ad altre " "finestre affiancate né saranno sollevate o ridimensionate insieme. Il " "comportamento dinamico di associazione dei tasti 'Window Focus' e anche il " "Tiling Popup non funzionerà più." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "Primo piano di gruppo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" "Quando una finestra è affiancata viene creato un gruppo di finestre. Se una " "finestra del gruppo viene messa in primo piano, anche le altre finestre del " "gruppo andranno in primo piano" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "Selettore app e finestre affiancate" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" "Questa opzione potrebbe entrare in conflitto con altre estensioni di " "selezione delle app (aka alt+Tab). Potrebbe essere necessario riattivare " "questa o le altre estensioni dopo averla abilitata." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "Spaziatura" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "Finestre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "Bordi dello schermo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "Bordo dello schermo in alto" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "Bordo dello schermo a sinistra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "Bordo dello schermo a destra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "Bordo dello schermo in basso" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "Finestre massimizzate" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "Scorciatoie dinamiche" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" "Le combinazioni di tasti per massimizzare e affiancare in alto/basso/" "sinistra/destra potrebbero cambiare il loro comportamento basato sullo stato " "di affiancamento della finestra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "Disabilita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "Non modificare il comportamento delle associazioni dei tasti" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "Stato attivo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" "Passa lo stato attivo alla finestra affiancata nella direzione della " "scorciatoia premuta" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "Stato affiancato" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" "Adatta lo stato di affiancamento alla scorciatoia premuta. Ad esempio, una " "finestra affiancata alla metà destra si affiancherà al quarto in basso a " "destra, se 'affianca in basso' è attivato" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "Stato affiancato (finestre)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" "Agisce come \"Stato affiancato\" ma se la finestra non è affiancata o è già " "affiancata in basso e la scorciatoia \"affianca in basso\" è attiva, riduce " "a icona la finestra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "Layout preferito" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "Sposta la finestra seguendo il layout preferito delle finestre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "Suggerimento finestra attiva" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "Non indicare la finestra focalizzata" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "Minimale" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" "Indica temporaneamente la finestra focalizzata quando si passa a un'area di " "lavoro con più finestre non sovrapposte" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "Sempre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" "Indica sempre la finestra focalizzata a meno che non sia ingrandita o a " "schermo intero. Ci sono problemi su Wayland con i popup di GTK4" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "Suggerimento colore" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "Il colore del riquadro che indica la finestra attiva" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "Dimensione del bordo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" "La dimensione del bordo della cornice che indica la finestra focalizzata per " "il suggerimento sempre attivo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "Dimensione del bordo interno" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" "Il bordo per il suggerimento sempre attivo che si estende all'interno della " "cornice della finestra. Questo ha lo scopo di coprire gli angoli " "arrotondati. Tuttavia, i popup di GTK4 su Wayland metteranno la finestra " "dietro il suggerimento per qualsiasi motivo..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "Animazioni" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "Affianca finestra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "Rimuovi affiancamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "Modalità di movimento della finestra predefinita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "Affiancamento ai bordi" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" "Spostando la finestra sui bordi o sugli angoli dello schermo si aprirà " "l'anteprima di affiancamento predefinita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "Affiancamento adattivo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" "Mentre viene trascinata, rilasciare una finestra su una finestra già " "affiancata, spingerà da parte la finestra sovrapposta." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" "L'anteprima di affiancamento seguirà il layout preferito nella pagina " "\"Layout\"" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "Ignora l'Assistente di affiancamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" "Usa affiancamento bordi senza le funzionalità dell'assistente di " "affiancamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "Altro" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "Monitora il periodo di tolleranza per il cambio" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" "Quando una finestra viene trascinata su un nuovo monitor, l'anteprima del " "riquadro si attaccherà al vecchio monitor per un tempo molto breve. In " "questo modo puoi affiancare le finestre 'lanciandole' verso qualsiasi bordo " "dello schermo anche se c'è un monitor confinante con quel bordo." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "Modalità di movimento a basse prestazioni" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" "Usare questo se c'è un ritardo quando si spostano le finestre. Questo sarà " "comunque ridurrà la precisione degli aggiornamenti dell'anteprima del " "riquadro." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "Adatta \"Affiancamento ai bordi\" al layout preferito" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "Per attivare la modalità \"Affiancamento adattivo\"" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "Ctrl" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "Alt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "Tasto destro" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "Per attivare la modalità \"Layout preferito\"" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "Ignora l'attivatore della modalità Tiling Assistant" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "Area di attivazione del bordo verticale" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "Area di attivazione del bordo orizzontale" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Timer dell'azione inversa nella parte superiore dello schermo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "Azione inversa nella parte superiore degli schermi orizzontali" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "Azione inversa nella parte superiore degli schermi verticali" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Ripristina dimensione finestra a" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" "Le finestre affiancate potrebbero non ripristinarsi correttamente su " "Wayland. Se ciò accade, selezionare \"Ripristina dimensione finestra a Fine " "trascinamento\"" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "Inizio trascinamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "Fine trascinamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Scorciatoie" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "Attiva/disattiva \"Popup finestre affiancate\"" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Editor delle finestre affiancate" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "Modalità guidata da tastiera per gestire le finestre affiancate" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Auto-affiancamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "Affianca/rimuove la finestra corrente in base ai riquadri visibili" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "Attiva/disattiva \"Sempre in primo piano\"" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Attiva/disattiva massimizza" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "Attiva/disattiva massimizza in verticale" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "Attiva/disattiva massimizza in orizzontale" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "Ripristina le dimensioni della finestra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "Sposta la finestra al centro" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Affianca in alto" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Affianca in basso" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Affianca a sinistra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Affianca a destra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "Affianca ad angolo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Affianca in alto a sinistra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Affianca in alto a destra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Affianca in basso a sinistra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Affianca in basso a destra" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "Affiancamento dei bordi senza Tiling Assistant" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "Affiancamento d'angolo senza Tiling Assistant" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "Debug" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "Mostra guide dei riquadri" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "Mostra guide dello spazio libero" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "Layout" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "Indicatore del pannello" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "Seleziona layout" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "Apre un popup che elenca tutti i layout disponibili" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "Aggiungi nuovo layout." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "Salva i layout sul disco. Le modifiche non valide andranno perdute!" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "Ricarica i layout dal disco - elimina tutte le modifiche non salvate." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "Impostazioni avanzate/sperimentali" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "Mostra più impostazioni nella finestra principale delle preferenze" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" "Sostituisci le scorciatoie. Premere \"spazio\" o \"invio\" mentre si " "registra una combinazione di tasti per aggiungerne una nuova a quelle " "esistenti." #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "Cancella scorciatoie" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "Popup finestre affiancate abilitato" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "Popup finestre affiancate disabilitato" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "Nessun layout valido definito." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "Layout popup: app non trovata." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "Digita per cercare..." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "Layout senza nome..." #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" "Impossibile avviare \"Editor delle finestre affiancate\", quando non è " "visibile alcuna finestra affiancata." #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "\"Guida utente\" per assistenza..." #~ msgid "" #~ "The keyboard shortcuts to maximize and tile to the top, bottom, left, and " #~ "right won't change their behavior based on the window's tiling state" #~ msgstr "" #~ "Le scorciatoie per ingrandire e affiancare in alto, in basso, a sinistra " #~ "e a destra non cambieranno il loro comportamento in base allo stato di " #~ "affiancamento della finestra" #~ msgid "" #~ "Switch focus to the tiled window in the direction of the pressed " #~ "shortcut, if there is one" #~ msgstr "" #~ "Sposta lo stato attivo sulla finestra affiancata nella direzione " #~ "indicata, se presente" #~ msgid "" #~ "Adapt the current window's tiling state to the pressed shortcut. For " #~ "instance, a window tiled to the right half will tile to the bottom-right " #~ "quarter, if 'tile to bottom' is activated" #~ msgstr "" #~ "Adatta lo stato di affiancamento della finestra corrente alla " #~ "scorciatoia. Ad esempio, una finestra affiancata a destra verrà " #~ "affiancata in basso a destra quando l'opzione \"affianca in basso\" è " #~ "attiva" #~ msgid "Other Window Movement Settings" #~ msgstr "Altre impostazioni di movimento della finestra" #~ msgid "Show Changelog in Preferences after an Update" #~ msgstr "Mostra Registro modifiche nelle Preferenze dopo un aggiornamento" #~ msgid "Tiling Window Switcher" #~ msgstr "Selettore finestre affiancate" #~ msgid "Replace App Switcher" #~ msgstr "Sostituisci selettore app" #~ msgid "" #~ "Replace the App Switcher (a. k. a. Alt+Tab) with a window switcher, which " #~ "previews the windows and tile groups" #~ msgstr "" #~ "Sostituisci selettore app (aka Alt+Tab) con un selettore che mostra le " #~ "anteprime delle finestre e dei gruppi di finestre affiancate" #~ msgid "Group Windows by App" #~ msgstr "Raggruppa le finestre per app" #~ msgid "" #~ "Windows of the same app are displayed as one item and can be cycled " #~ "through with the key above Tab" #~ msgstr "" #~ "Le finestre della stessa app vengono visualizzate come un singolo " #~ "elemento e possono essere selezionate con il tasto sopra Tab" #~ msgid "Hidden Settings" #~ msgstr "Impostazioni nascoste" Tiling-Assistant-46/translations/ja.po000066400000000000000000000553031457776040200201770ustar00rootroot00000000000000# Japanese translations for Tiling-Assistant # Copyright (C) 2021 THE Tiling-Assistant'S COPYRIGHT HOLDER # This file is distributed under the same license as the Tiling-Assistant package. # k-fog , 2021. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2021-11-03 17:47+0900\n" "Last-Translator: k-fog \n" "Language-Team: Japanese <>\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "バグの報告" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "ユーザーガイド" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "ライセンス" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "変更ログ" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "高度な設定" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "一般" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "タイリングポップアップ" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "ウィンドウの整列時に表示" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "全てのワークスペースのアプリケーションを含む" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "タイルグループ" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "タイルグループのフォーカスを同期する" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "隙間" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "ウィンドウ" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "画面端" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "最大化されたウィンドウ" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "動的なキーバインドの動作" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "無効" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "ウィンドウフォーカス" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "整列状態" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "整列状態(ウィンドウ)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" "基本動作は[整列状態]と同じですが、もしウィンドウが整列されていないか、すでに" "下に配置されている状態で[下に配置]が実行された場合、ウィンドウを最小化しま" "す。" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "お気に入りのレイアウト" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "お気に入りのレイアウトに従ってウィンドウを移動" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "アニメーション" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "整列時" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "整列解除時" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "端に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" "ウィンドウを画面端または角に移動すると、デフォルトのタイルプレビューを表示す" "る" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "マウス右ボタン" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "上下の整列プレビュー反応範囲" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "左右の整列プレビュー反応範囲" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "画面上端での動作切り替え時間" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "横長の画面で画面上端での動作を逆にする" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "縦長の画面で画面上端での動作を逆にする" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" "Waylandでは、整列されたウィンドウが適切にサイズを復元できない場合があります。" "その場合、'Restore Window Size on Grab End'を使用してください。" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "キーバインド" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "[タイリングポップアップ]の切り替え" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "タイル編集モード" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "整列したウィンドウをキーボードで操作するモード" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "最大化切り替え" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "上に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "下に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "左に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "右に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "角に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "左上に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "右上に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "左下に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "右下に配置" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "レイアウト" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "レイアウトを探す" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "新しいレイアウトを追加" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "レイアウトを保存する(無効な設定は失われます!)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "保存されていない変更を破棄し、レイアウトを再読込する。" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "高度な/実験な機能の設定" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "タイリングポップアップが有効になりました" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "タイリングポップアップが無効になりました" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "ポップアップレイアウト:アプリケーションが見つかりません" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "入力して検索..." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "無題のレイアウト..." #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" "整列されたウィンドウが表示されていない場合、[タイル編集モード]に切り替えられ" "ません。" #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "[ユーザーガイド]からヘルプを参照..." #~ msgid "" #~ "The keyboard shortcuts to maximize and tile to the top, bottom, left, and " #~ "right won't change their behavior based on the window's tiling state" #~ msgstr "" #~ "最大化や上下左右への配置を行うキーボードショートカットは、ウィンドウの整列" #~ "状態に応じて動作を変えません。" #~ msgid "" #~ "Switch focus to the tiled window in the direction of the pressed " #~ "shortcut, if there is one" #~ msgstr "" #~ "押されたショートカットの方向に整列したウィンドウがある場合、そのウィンドウ" #~ "にフォーカスを切り替えます" #~ msgid "" #~ "Adapt the current window's tiling state to the pressed shortcut. For " #~ "instance, a window tiled to the right half will tile to the bottom-right " #~ "quarter, if 'tile to bottom' is activated" #~ msgstr "" #~ "現在のウィンドウの整列状態を、押されたショートカットに適応させます。例え" #~ "ば、右半分に配置されたウィンドウは、[下に配置]が実行された場合、右下に配置" #~ "されます" #~ msgid "Show Changelog in Preferences after an Update" #~ msgstr "アップデート後、設定画面に変更ログを表示" #~ msgid "Hidden Settings" #~ msgstr "隠されし設定" #~ msgid "Split Tiles" #~ msgstr "タイルを分割" #~ msgid "" #~ "Your favorite layout will be used as the 'Favorite Layout' when moving a " #~ "window." #~ msgstr "" #~ "あなたのお気に入りのレイアウトは、ウィンドウを移動した時、[お気に入りのレ" #~ "イアウト]として使用されるようになります。" #~ msgid "Keyboard Shortcuts" #~ msgstr "キーボードショートカット" #~ msgid "Change favorite Layout" #~ msgstr "お気に入りのレイアウトを変更" #~ msgid "Moving Windows" #~ msgstr "ウィンドウの移動" #~ msgid "No valid popup layouts defined." #~ msgstr "有効なポップアップレイアウトが定義されていません" #~ msgid "Raise Tile Groups together" #~ msgstr "タイルグループのフォーカスを同期する" #~ msgid "Window Gaps" #~ msgstr "ウィンドウ間の隙間" #~ msgid "Gaps on Maximized Windows" #~ msgstr "最大化されたウィンドウの隙間" #~ msgid "" #~ "This setting is intended for Wayland users. Tiled windows may not " #~ "properly restore their size when they are being grabbed on Wayland.\n" #~ "\n" #~ "If that is the case, you can try 'Restore Window Size on Grab End' " #~ "instead." #~ msgstr "" #~ "この設定はWaylandユーザーのためのものです。Waylandでは、整列されたウィンド" #~ "ウが適切にサイズを復元できない場合があります。\n" #~ "\n" #~ "その場合、代わりに'Restore Window Size on Grab End'を試すことができます。" #~ msgid "Inverse Top Screen Edge Action:" #~ msgstr "画面上端での動作を入れ替える" #~ msgid "Landscape Displays" #~ msgstr "横長の画面" #~ msgid "Portrait Displays" #~ msgstr "縦長の画面" #~ msgid " General " #~ msgstr " 一般 " #~ msgid "Hidden Settings" #~ msgstr "隠されし設定" #~ msgid "Tiling Popup: Current Workspace only" #~ msgstr "タイリングポップアップ:現在のワークスペースのみ" #~ msgid "Tile Editing Mode: Focus Color" #~ msgstr "タイル編集モード:フォーカス色" #~ msgid "Tile Animations" #~ msgstr "タイル化アニメーション" #~ msgid "Untile Animations" #~ msgstr "タイル化解除アニメーション" #~ msgid "Vertical Tile Preview Trigger Area" #~ msgstr "上下整列プレビュー反応範囲" #~ msgid "Horizontal Tile Preview Trigger Area" #~ msgstr "左右整列プレビュー反応範囲" Tiling-Assistant-46/translations/main.pot000066400000000000000000000410651457776040200207150ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "" Tiling-Assistant-46/translations/nl.po000066400000000000000000000543351457776040200202220ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2022-12-03 18:48+0100\n" "Last-Translator: Philip Goto \n" "Language-Team: \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.1.1\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "Probleem rapporteren" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "Gebruikershandleiding" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "Licentie" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "Wijzigingslogboek" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "Geavanceerd…" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "Algemeen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Tegelpop-upvenster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "Openen na tegelen venster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "Apps van alle werkbladen tonen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "Tegelgroepen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "Tegelgroepen uitschakelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "Samen naar voren brengen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "App-wisselaar en tegelingspop-up" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "Ruimtes" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "Vensters" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "Schermranden" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "Schermrand boven" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "Schermrand links" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "Schermrand rechts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "Schermrand onder" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "Gemaximaliseerde vensters" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "Dynamisch sneltoetsgedrag" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "Uitgeschakeld" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "Vensterfocus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "Tegelstatus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "Tegelstatus (Windows)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "Favoriete indeling" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "Hint van actieve venster" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "Minimaal" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "Altijd" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "Hintkleur" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "Randbreedte" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "Binnenste randbreedte" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "Animaties" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "Tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "Onttegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "Standaardvensterbeweginsmodus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "Randtegeling" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "Adaptieve tegeling" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "Tegelingsassistent negeren" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "Overig" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "Wachttijd bij schermwissel" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "Bewegingsmodus met lage prestaties" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "Ctrl" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "Alt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "RMK" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "Super" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Randactie op bovenste beeldscherm omdraaien - Tijdklok" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Vensterafmetingen herstellen bij" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "Vastpakpositie" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "Einde van vastpakpositie" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Sneltoetsen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "Tegelpop-upvenster tonen/verbergen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Tegelbewerkmodus" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Automatisch tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "Het huidige venster (ont)tegelen gebaseerd op zichtbare tegels" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "‘Altijd voorop’ omschakelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Maximaliseren omschakelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "Verticale maximalisatie omschakelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "Horizontale maximalisatie omschakelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "Venstergrootte herstellen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "Venster naar midden verplaatsen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Naar boven tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Naar onder tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Naar links tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Naar rechts tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "Hoektegeling" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Naar linksboven tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Naar rechtsboven tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Naar linksonder tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Naar rechtsonder tegelen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "Randtegeling zonder tegelingsassistent" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "Hoektegeling zonder tegelingsassistent" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "Foutopsporing" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "Indelingen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "Paneelindicator" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "Naar indeling zoeken" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "Voeg een nieuwe indeling toe." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "Geavanceerde/experimentele instellingen" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "Tegelingspop-up ingeschakeld" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "Tegelingspop-up is uitgeschakeld" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "Geen geldige indelingen gedefinieerd." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "Typ om te zoeken…" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "Naamloze indeling…" #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "‘Gebruikershandleiding’ voor hulp…" #~ msgid "Raise Tile Groups together" #~ msgstr "Tegelgroepen tegelijk focussen" #~ msgid "Focus" #~ msgstr "Focus" #~ msgid "Window Gaps" #~ msgstr "Ruimte tussen vensters" #~ msgid "Gaps on Maximized Windows" #~ msgstr "Ruimte tussen gemaximaliseerde vensters" #~ msgid "" #~ "This setting is intended for Wayland users. Tiled windows may not " #~ "properly restore their size when they are being grabbed on Wayland.\n" #~ "\n" #~ "If that is the case, you can try 'Restore Window Size on Grab End' " #~ "instead." #~ msgstr "" #~ "Deze optie is bedoeld voor Wayland-gebruikers. Getegelde vensters worden " #~ "mogelijk niet goed hersteld als ze door Wayland worden onderschept.\n" #~ "\n" #~ "Als dat het geval is, probeer dan de optie ‘Vensterafmetingen herstellen " #~ "bij vastpakken van uiteinde’." #~ msgid "Inverse Top Screen Edge Action:" #~ msgstr "Randactie op bovenste beeldscherm omdraaien:" #~ msgid "Landscape Displays" #~ msgstr "Horizontale beeldschermen" #~ msgid "Portrait Displays" #~ msgstr "Verticale beeldschermen" #~ msgid "" #~ "The focused window will try to fill the free screen space as good as " #~ "possible based on the tiled windows around it." #~ msgstr "" #~ "Het gefocuste venster zal trachten de vrij schermruimte zo goed mogelijk " #~ "te benutten op basis van naburige vensters." #~ msgid " General " #~ msgstr " Algemeen " #~ msgid " Side Tiling " #~ msgstr " Zijwaarts tegelen " #~ msgid " Corner Tiling " #~ msgstr " Hoektegelen " #~ msgid "Tiling Assistant" #~ msgstr "Tegelassistent" #~ msgid "" #~ "If you want to report a bug or need help,\n" #~ "\n" #~ "please open an issue on Github." #~ msgstr "" #~ "Als u een bug wilt melden of hulp wilt vragen,\n" #~ "\n" #~ "dan kunt u een ‘issue’ openen op GitHub." #~ msgid "" #~ "List of known INCOMPATIBLE apps/extensions/limitations." #~ msgstr "" #~ "Lijst met bekende INCOMPATIBELE toepassingen/" #~ "uitbreidingen/beperkingen." #~ msgid "" #~ "The GUIDE offers a detailed explanation of every " #~ "feature." #~ msgstr "" #~ "De ZELFSTUDIEPAGINA (Engelstalig) bevat uitgebreide " #~ "hulp omtrent alle functies." #~ msgid "" #~ "The CHANGELOG lists the differences between each " #~ "extension version." #~ msgstr "" #~ "Het WIJZIGINGSLOG toont de verschillen tussen elke " #~ "uitbreidingsversie." #~ msgid "" #~ "This extension is licensed under the GNU General Public License, version 2 " #~ "or later and comes with NO WARRANTY. A copy of this " #~ "license can be found in the Github repository." #~ msgstr "" #~ "Deze uitbreiding is uitgebracht onder de voorwaarden van de GNU General " #~ "Public License, versie 2 of nieuwer, en wordt ZONDER ENIGE " #~ "GARANTIE geleverd. Een kopie van deze licentie is te vinden in " #~ "de GitHub-repo." #~ msgid "Help" #~ msgstr "Hulp" #~ msgid "Hidden Settings" #~ msgstr "Verborgen voorkeuren" #~ msgid "Tiling Popup: Current Workspace only" #~ msgstr "Tegelpop-upvenster: alleen op huidige werkblad" #~ msgid "Tile Editing Mode: Focus Color" #~ msgstr "Tegelbewerkmodus: focuskleur" #~ msgid "Tile Animations" #~ msgstr "Tegelanimaties" #~ msgid "Untile Animations" #~ msgstr "Onttegelanimaties" #~ msgid "Vertical Tile Preview Trigger Area" #~ msgstr "Verticale tegelvoorvertoning: actiegebied" #~ msgid "Horizontal Tile Preview Trigger Area" #~ msgstr "Horizontale tegelvoorvertoning: actiegebied" #~ msgid "Debugging: Show Tiled Rects" #~ msgstr "Foutopsporing: tegelrechthoeken tonen" #~ msgid "Debugging: Show Free Screen Rects" #~ msgstr "Foutopsporing: vrije tegelrechthoeken tonen" Tiling-Assistant-46/translations/pt_BR.po000066400000000000000000000762011457776040200206130ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2022-04-11 16:53-0300\n" "Last-Translator: Fernando Omori \n" "Language-Team: \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.3\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "Reportar um Bug" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "Guia do Usuário" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "Licença" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "Registro de Mudanças" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "Avançado..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "Geral" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Popup de Ladrilhamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "Abrir após ladrilhar uma janela" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "Incluir apps de todos os espaços de trabalho" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "Grupos de Ladrilhos" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "Desabilitar Grupos de Ladrilhos" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" "Ladrilhos não irão mais adaptar seu tamanho à outros ladrilhos nem " "levantados ou redimensionados juntos. O Comportamento de Atalhos de Teclado " "Dinâmico 'Foco da Janela' e o 'Popup de Ladrilhamento' não mais funcionarão." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "Levantar juntos" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" "Um grupo de ladrilhos é criado quando uma janela se torna um ladrilho. Se um " "ladrilho é levantado, levante os outros do grupo também" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "Alternador de apps e Popup de ladrilhamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" "Isso pode entrar em conflito com outros extensões alternadoras de apps " "(também conhecidas como de alt+tab). Talvez você deva reabilitar esta ou a " "outra extensão após ativar esta opção" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "Espaçamentos" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "Janelas" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "Bordas da Tela" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "Borda Superior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "Borda Esquerda" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "Borda Direita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "Borda Inferior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "Janelas Maximizadas" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "Comportamento de Atalhos de Teclado Dinâmico" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" "Os atalhos de teclado e o ladrilho para topo/baixo/esquerda/direita podem " "mudar o comportamento baseado no estado do ladrilho" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "Desativado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "Não mude o comportamento das teclas de atalho" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "Foco da Janela" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "Mudar foco para o ladrilho na direção do atalho utilizado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "Estado de Ladrilhamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" "Adaptar o estado do ladrilhamento ao atalho utilizado. Por exemplo, um " "ladrilho à metade da direita vai ocupar o quadrante da direita inferior, se " "o 'ladrilhar abaixo' estiver ativado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "Estado de Ladrilhamento (Janelas)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" "Parecido com 'Estado de Ladrilhamento' mas se a janela não é ladrilhada ou " "já está abaixo e o atalho 'ladrilhar abaixo' for ativado, minimize a janela" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "Layout favorito" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "Mover a janela junto ao seu Layout favorito" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "Ativar Dica de Janela" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "Não indicar a janela em foco" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "Minimalista" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" "Temporariamente indicar a janela focada quando trocar de área de trabalho " "com múltiplas janelas não sobrepostas" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "Sempre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" "Sempre indicar a janela focada a menos que esteja maximizada ou tela cheia. " "Há problemas no Wayland com popups GTK4" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "Cor da Dica" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "A cor da moldura indicando a janela em foco" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "Tamanho da Borda" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" "O tamanho da borda da moldura indicando a janela em foco para a dica sempre " "ativa" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "Tamanho Borda Interno" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" "A borda para dica sempre ativa alcançando dentro da moldura da janela. Isso " "serve para cobrir os cantos arrendondados. Entretanto, popups GTK4 no " "Wayland vão colocar a janela atrás da dica por algum motivo..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "Animações" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "Ladrilhamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "Desladrilhamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "Modo Padrão de Movimento de Janela" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "Ladrilhamento às bordas" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" "Mover a janela às laterais da tela ou aos cantos abrirá a prévia do ladrilho " "padrão" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "Ladrilhamento Adaptivo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" "Soltar uma janela estando encima de um ladrilho empurrará a(s) janela(s) " "sobreposta(s) ao lado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" "A prévia do ladrilho se continuará usando seu Layout favorito da página " "'Layouts'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "Ignore o Assistente de Ladrilhamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" "Use Ladrilhamento de Borda sem os recursos do Assistente de Ladrilhamento" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "Outro" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "Período de Carência para Troca de Monitor" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" "Quando a janela é arrastado para um novo monitor o preview do ladrilho vai " "permanecer no monitor antigo for um momento. Dessa forma, você pode " "organizar ladrilhos 'jogando' eles em direção a qualquer canto da tela se o " "monitor estiver limítrofe aquela borda." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "Modo de Movimento de Baixo Desempenho" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" "Use isso se houver um atraso ao mover janelas. Isso, no entanto, diminuirá a " "precisão das atualizações de visualização dos blocos." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "Adaptar 'Ladrilhamento às Bordas' ao seu Layout Favorito" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "Ativador de Modo 'Ladrilhamento Adaptivo'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "Ctrl" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "Alt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "Clique Secundário" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "Super" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "Ativator de Modo de Movimentação de 'Layout Favorito'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "Ativador do Modo 'Ignorar Assistente de Ladrilhamento'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "Área da Borda Vertical de Gatilho da Prévia" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "Área da Borda Horizontal de Gatilho da Prévia" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Temporizador de ação inversa da borda superior da tela" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "Ação Inversa para Telas em modo Paisagem da Borda Superior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "Ação Inversa para Telas em modo Retrato da Borda Superior" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Restaurar Tamanho da Janela ao" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" "Janelas ladrilhadas podem não restaurar seu tamanho apropriadamente no " "Wayland. Se esse é seu caso, use 'Restaurar Tamanho da Janela ao Soltar'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "ao Pegar" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "ao Soltar" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Atalhos de teclado" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "Alternar 'Popup de Ladrilhamento'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Modo de Edição de Ladrilho" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "Um modo que usa o teclado para gerenciar suas janelas ladrilhadas" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Auto-Ladrilhar" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "Ladrilhar/Desladrilhar a janela atual conforme os ladrilhos visíveis" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "Alternar 'Sempre no Topo'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Alternar Maximização" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "Alternar Maximização Vertical" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "Alternar Maximização Horizontal" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "Restaurar Tamanho da Janela" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "Mover Janela ao Centro" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Ladrilhar acima" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Ladrilhar abaixo" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Ladrilhar à esquerda" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Ladrilhar à direita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "Ladrilhamento aos Cantos" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Ladrilhar acima e esquerda" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Ladrilhar acima e direita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Ladrilhar abaixo e esquerda" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Ladrilhar abaixo e direita" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "Ladrilhamento da borda sem Assistente" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "Ladrilhamento do Canto sem Assistente" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "Debugging" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "Mostrar Retângulos Ladrilhados" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "Mostrar Retângulos de Espaço Livre" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "Layouts" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "Indicador de Painel" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "Procurar por um Layout" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "Abrir um popup listando todos os Layouts disponíveis" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "Adicionar um novo Layout." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "Salve os Layouts no disco. As alterações inválidas serão perdidas!" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" "Recarregue os Layouts do disco - descartando todas as alterações não salvas." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "Configurações Avançadas / Experimentais" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "Mostrar mais configurações na janela de preferências principal" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" "Substitui os atalhos de teclados. Aperte 'espaço' ou 'return' enquanto " "adicionando um atalho para adicionar um novo atalho alternativo." #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "Limpar os atalhos de teclado" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "Janela instantânea de ladrilhamento ativada" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "Janela instantânea de ladrilhamento foi desativada" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "Nenhum Layout válido definido." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "Layouts de Janela Instantânea: App não encontrado." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "Digite para procurar..." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "Layout sem nome..." #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" "Não é possível entrar no 'Modo de Edição de Ladrilho' se não há janelas " "ladrilhadas visíveis." #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "'Guia do Usuário' para ajuda..." #~ msgid "" #~ "The keyboard shortcuts to maximize and tile to the top, bottom, left, and " #~ "right won't change their behavior based on the window's tiling state" #~ msgstr "" #~ "Os atalhos de teclado para maximizar e ladrilhar para cima, baixo, " #~ "esquerda, e direita não mudarão seu comportamento baseado no estado de " #~ "ladrilhamento da janela" #~ msgid "" #~ "Switch focus to the tiled window in the direction of the pressed " #~ "shortcut, if there is one" #~ msgstr "" #~ "Mudar foco para o ladrilho na direção do atalho pressionado, se há um" #~ msgid "" #~ "Adapt the current window's tiling state to the pressed shortcut. For " #~ "instance, a window tiled to the right half will tile to the bottom-right " #~ "quarter, if 'tile to bottom' is activated" #~ msgstr "" #~ "Adaptar o estado de ladrilhamento da janela atual ao atalho pressionado. " #~ "Por exemplo, uma janela ladrilhada ao lado direito irá ao canto inferior " #~ "direito se 'ladrilhar abaixo' for ativado" #~ msgid "Other Window Movement Settings" #~ msgstr "Outras Configurações de Movimento de Janela" #~ msgid "Show Changelog in Preferences after an Update" #~ msgstr "Mostrar Registro de Mudanças em Preferências após uma Atualização" #~ msgid "Tiling Window Switcher" #~ msgstr "Alternador de Janelas Ladrilhadas" #~ msgid "Replace App Switcher" #~ msgstr "Substituir alternador de apps" #~ msgid "" #~ "Replace the App Switcher (a. k. a. Alt+Tab) with a window switcher, which " #~ "previews the windows and tile groups" #~ msgstr "" #~ "Substituir o alternador de apps (também conhecido como alt+tab) por um " #~ "alternador de janelas, que prevê as janelas e grupos de ladrilhos" #~ msgid "Group Windows by App" #~ msgstr "Agrupar Janelas por App" #~ msgid "" #~ "Windows of the same app are displayed as one item and can be cycled " #~ "through with the key above Tab" #~ msgstr "" #~ "Janelas do mesmo app são mostrados como um item e podem ser alternadas " #~ "usando a tecla acima de Tab" #~ msgid "Hidden Settings" #~ msgstr "Configurações Ocultas" #~ msgid "No valid popup layouts defined." #~ msgstr "Nenhum Layout de janela instantânea válido definido." #~ msgid "Raise Tile Groups together" #~ msgstr "Elevar Grupos de Ladrilhos juntos" #~ msgid "" #~ "The keyboard shortcuts to maximize and tile to the top, bottom, left, and " #~ "right may change depending on the tiling state of the focused window.\n" #~ "\n" #~ "Disabled: The shortcuts won't change their behavior based on the " #~ "window's tiling state.\n" #~ "\n" #~ "Focus: If the current window is tiled and there is a tiled window " #~ "in the direction of the shortcut, switch focus to that tiled window " #~ "instead of tiling the current window.\n" #~ "\n" #~ "Tiling State: If the current window is tiled, it adapts to the " #~ "pressed shortcut. For example, if the current window is tiled to the " #~ "right half of your monitor and the shortcut to tile to the bottom is " #~ "activated, the window will tile to the bottom-right quarter instead of " #~ "the bottom half.\n" #~ "\n" #~ "Tiling State (Windows): Like 'Tiling State' but if the window " #~ "isn't tiled or is already tiled to the bottom and the 'tile to bottom' " #~ "shortcut is activated, minimize the window." #~ msgstr "" #~ "Os atalhos de teclado para maximizar e ladrilhar na parte superior, " #~ "inferior, esquerda e direita podem mudar dependendo do estado de ladrilho " #~ "da janela em foco.\n" #~ "\n" #~ "Desativado: Os atalhos não mudam seu comportamento com base no " #~ "estado de ladrilho da janela.\n" #~ "\n" #~ "Foco: Se a janela atual está ladrilhada e houver uma janela " #~ "ladrilhada na direção do atalho, mude o foco para essa janela ladrilhada " #~ "em vez de ladrilhar a janela atual.\n" #~ "\n" #~ "Estado de Ladrilhamento: Se a janela atual está ladrilhada, ela se " #~ "adapta ao atalho pressionado. Por exemplo, se a janela atual está " #~ "ladrilhada à metade direita do monitor e o atalho para ladrilhar abaixo " #~ "for ativado, a janela será ladrilhada na parte inferior direita em vez da " #~ "metade inferior.\n" #~ "\n" #~ "Estado de Ladrilhamento (Janelas): Como 'Estado de Ladrilhamento', " #~ "mas se a janela não está ladrilhada ou já estiver ladrilhada na parte " #~ "inferior e o atalho 'Ladrilhar Abaixo' for ativado, minimiza a janela." #~ msgid "Focus" #~ msgstr "Foco" #~ msgid "Window Gaps" #~ msgstr "Espaçamentos entre janelas" #~ msgid "Gaps on Maximized Windows" #~ msgstr "Espaçamento em Janelas Maximizadas" #~ msgid "" #~ "This setting is intended for Wayland users. Tiled windows may not " #~ "properly restore their size when they are being grabbed on Wayland.\n" #~ "\n" #~ "If that is the case, you can try 'Restore Window Size on Grab End' " #~ "instead." #~ msgstr "" #~ "Esta configuração é destinada para usuários do Wayland. Janelas " #~ "ladrilhadas talvez não restaurem corretamente seus tamanhos quando\n" #~ "forem capturadas no Wayland.\n" #~ "\n" #~ "Se for este o caso, você pode tentar 'Restaurar Tamanho da Janela' em " #~ "'Capturar no Final'." #~ msgid "Inverse Top Screen Edge Action:" #~ msgstr "Inverter Ação da Borda Superior da Tela:" #~ msgid "Landscape Displays" #~ msgstr "Telas Paisagem" #~ msgid "Portrait Displays" #~ msgstr "Telas Retrato" #~ msgid "" #~ "The focused window will try to fill the free screen space as good as " #~ "possible based on the tiled windows around it." #~ msgstr "" #~ "A janela em foco tentará preencher o espaço livre da melhor forma " #~ "possível baseando-se nas janelas ladrilhadas ao redor." #~ msgid " General " #~ msgstr " Geral " #~ msgid " Side Tiling " #~ msgstr " Ladrilhamento de Borda " #~ msgid " Corner Tiling " #~ msgstr " Ladrilhamento de Canto " #~ msgid "Search Popup Layout" #~ msgstr "Layout de Janela de Pesquisa" #~ msgid "Popup Layouts" #~ msgstr "Layouts de Janelas Instantâneas" #~ msgid "Tiling Assistant" #~ msgstr "Tiling Assistant" #~ msgid "" #~ "If you want to report a bug or need help,\n" #~ "\n" #~ "please open an issue on Github." #~ msgstr "" #~ "Se você quer reportar um bug ou precisa de ajuda,\n" #~ "\n" #~ "por favor abra uma \"issue\" no Github." #~ msgid "" #~ "List of known INCOMPATIBLE apps/extensions/limitations." #~ msgstr "Lista de apps/extensões/limitações INCOMPATÍVEIS." #~ msgid "" #~ "The GUIDE offers a detailed explanation of every " #~ "feature." #~ msgstr "" #~ "O GUIA oferece uma explicação detalhada para cada " #~ "função." #~ msgid "" #~ "The CHANGELOG lists the differences between each " #~ "extension version." #~ msgstr "" #~ "O CHANGELOG lista as diferenças entre cada versão da " #~ "extensão." #~ msgid "" #~ "This extension is licensed under the GNU General Public License, version 2 " #~ "or later and comes with NO WARRANTY. A copy of this " #~ "license can be found in the Github repository." #~ msgstr "" #~ "Esta extensão está licenciada sob a GNU General Public License, versão 2 " #~ "ou posterior e NÃO VEM COM GARANTIAS. Uma cópia desta " #~ "licença pode ser encontrada no repositório do Github." #~ msgid "Help" #~ msgstr "Ajuda" #~ msgid "Hidden Settings" #~ msgstr "Configurações Ocultas" #~ msgid "Tiling Popup: Current Workspace only" #~ msgstr "" #~ "Janela Instantânea de Ladrilhamento: Espaço de Trabalho atual somente" #~ msgid "Tile Editing Mode: Focus Color" #~ msgstr "Modo de Edição de Ladrilho: Cor de Foco" #~ msgid "Tile Preview: Secondary Mode Activator" #~ msgstr "Pré-visualização de Ladrilho: Ativador do Modo Secundário" #~ msgid "Tile Preview: Default to Secondary Mode" #~ msgstr "Pré-visualização de Ladrilho: Padrão para Modo Secundário" #~ msgid "Tile Animations" #~ msgstr "Animações de Ladrilhamento" #~ msgid "Untile Animations" #~ msgstr "Animações de Desladrilhamento" #~ msgid "Vertical Tile Preview Trigger Area" #~ msgstr "Área de gatilho de pré-visualização de ladrilho vertical" #~ msgid "Horizontal Tile Preview Trigger Area" #~ msgstr "Área de gatilho de pré-visualização de ladrilho horizontal" #~ msgid "Debugging: Show Tiled Rects" #~ msgstr "Depurando: Mostrar Retângulos Ladrilhados" #~ msgid "Debugging: Show Free Screen Rects" #~ msgstr "Depurando: Mostrar Retângulos de Tela Livre" #~ msgid "Nameless Layout..." #~ msgstr "Layout sem nome..." #~ msgid "Layout" #~ msgstr "Layout" #~ msgid "Check out the 'Guide' in the repository (see the 'Help' Tab)." #~ msgstr "Verifique o 'Guia' no repositório (veja a aba 'Ajuda')." #~ msgid "This tooltip for help..." #~ msgstr "Esta dica para ajuda..." Tiling-Assistant-46/translations/uk.po000066400000000000000000000657161457776040200202350ustar00rootroot00000000000000# Ukrainian translation of the Tiling Assistant GNOME Shell extension. # Copyright (C) 2024 Tiling-Assistant Contributors # This file is distributed under the same license as the Tiling-Assistant package. # Yevhen Popok , 2024. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: 2024-01-14 14:43+0200\n" "Last-Translator: Yevhen Popok \n" "Language-Team: \n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.4\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "Повідомити про ваду" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "Довідка" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "Ліцензія" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "Список змін" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "Додатково" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "Загальне" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "Спливаюче вікно мозаїки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "Відкривати після укладання вікна як плитки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "Включити програми з усіх робочих просторів" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "Групи плиток" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "Не використовувати групи плиток" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" "Вікна, укладені як плитки, більше не будуть припасовуватися до розмірів " "інших вікон мозаїки, як і не будуть одночасно підійматися та змінювати свої " "розміри. Cпливаюче вікно мозаїки та динамічні клавіатурні скорочення " "'Фокусування вікон' також перестануть працювати." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "Підіймати одночасно" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" "Група плиток формується під час укладання вікна як плитки. Коли підіймається " "одне вікно мозаїки, то інші вікна, що належать до групи плиток, підіймаються " "також" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "Перемикач програм та спливаюче вікно мозаїки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" "Це може створити несумісність з іншими розширеннями перемикача програм " "(alt+Tab). Можливо, вам доведеться переувімкнути поточне, або ж інше " "розширення після зміни цього параметра" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "Відступи" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "Вікна" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "Краї екрана" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "Верхній край екрана" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "Лівий край екрана" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "Правий край екрана" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "Нижній край екрана" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "Розгорнуті вікна" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "Поведінка динамічних клавіатурних скорочень" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" "Клавіатурні скорочення розгортання та укладання згори/знизу/ліворуч/" "праворуч, можуть змінювати свою поведінку в залежності від розміщення вікна" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "Вимкнено" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "Не змінювати поведінку клавіатурних скорочень" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "Фокусування вікон" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "Перемикати фокус на вікно мозаїки у напрямку клавіатурного скорочення" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "Положення плиток " #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" "Змінювати положення плиток в залежності від використання клавіатурного " "скорочення. Наприклад, вікно, укладене на правій половині, при активації " "'укласти знизу', переміститься до правої нижньої чверті" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "Положення плиток (вікна)" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" "Відмінність від 'Положення плиток' полягає в тому, що у разі, коли вікно не " "укладене чи укладене знизу, активація скорочення 'укласти знизу' приховає " "вікно" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "Улюблений макет" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "Розміщувати вікна, як на улюбленому макеті" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "Підказка щодо активного вікна" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "Не позначати вікно в фокусі" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "Мінімально" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" "Тимчасово позначати вікно в фокусі під час перемикання на робочий простір з " "декількома вікнами, що не перекриваютьcя" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "Завжди" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" "Завжди позначати вікно з фокусом. Виключення становлять розгорнуті та " "повноекранні вікна. Є проблеми зі спливаючими вікнами GTK4 на Wayland" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "Колір підказки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "Колір рамки, що позначає вікно з фокусом" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "Розмір рамки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" "Розмір рамки, яка позначає вікно з фокусом для завжди активної підказки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "Розмір внутрішньої рамки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" "Рамка завжди активної підказки всередині вікна. Призначена для покриття " "заокруглених кутів. Проте, спливаючі вікна GTK4 на Wayland з якоїсь причини " "розміщуються за підказкою..." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "Анімації" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "Укладання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "Відокремлення" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "Типовий режим переміщення вікон" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "Укладання від краю" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" "Після пересування вікна до краю чи кута екрана буде відкриватися типове " "спливаюче вікно пропозиції щодо укладання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "Адаптивне укладання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" "Якщо відпустити захоплене вікна над частиною мозаїки, то перекрите(-і) " "вікно(-а) посунуться вбік" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" "Пропозиція щодо укладання буде формуватися в залежності від вашого " "улюбленого макета зі сторінки 'Макети'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "Ігнорувати Tiling Assistant" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "Використовувати 'Укладання від краю' без функціоналу Tiling Assistant" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "Інше" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "Затримка під час переміщення між моніторами" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" "Коли вікно перетягується на інший монітор, пропозиція щодо укладання " "короткочасно активується на початковому моніторі. Таким чином, є можливість " "укладати вікна, 'cкидаючи' їх до краю екрана, навіть якщо монітори межують " "по цьому краю." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "Режим переміщення за низької продуктивності" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" "Використовуйте у разі, якщо є затримка при переміщенні вікон. Зауважте, що " "це знизить точність оновлення пропозиції щодо укладання." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "'Укладання від краю' буде адаптовано до вашого улюбленого макету" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "Активує переміщення в режимі 'Адаптивне укладання'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "Ctrl" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "Alt" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "Права кнопка миші" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "Super" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "Активує переміщення в режимі 'Улюблений макет'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "Активує переміщення в режимі 'Ігнорувати Tiling Assistant'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "" "Ділянка біля вертикальної межі, на якій активується пропозиції щодо укладання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "" "Ділянка біля горизонтальної межі, на якій активується пропозиції щодо " "укладання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "Таймер зворотної дії у верхній частині екрана" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "" "Зворотня дія у верхній частині екрана для дисплеїв з альбомною орієнтацією" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "" "Зворотня дія у верхній частині екрана для дисплеїв з портретною орієнтацією" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "Відновлювати розмір під час" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" "Вікна, укладені як плитки, можуть неправильно відновлювати свої розміри на " "Wayland. В такому разі використовуйте опцію 'Відновлювати розмір під час " "відпускання'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "захоплення" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "відпускання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "Клавіатурні скорочення" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "Увімкнути 'Спливаюче вікно мозаїки'" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "Режим редагування мозаїки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "Керування вікнами мозаїки за допомогою клавіатури" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "Укласти автоматично" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "Укласти/відокремити поточне вікно з урахуванням видимих вікон мозаїки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "Завжди зверху" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "Розгортання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "Вертикальне розгортання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "Горизонтальне розгортання" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "Відновити розмір вікна" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "Перемістити вікно до центру" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "Укласти згори" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "Укласти знизу" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "Укласти ліворуч" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "Укласти праворуч" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "Укладання від кута" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "Укласти згори ліворуч" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "Укласти згори праворуч" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "Укласти знизу ліворуч" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "Укласти знизу праворуч" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "Укладання від краю без використання Tiling Assistant" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "Укладання від кута без використання Tiling Assistant" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "Зневадження" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "Показати прямокутники мозаїки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "Показати незайняті прямокутники мозаїки" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "Макети" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "Індикатор на панелі" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "Пошук макета" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "Викликати спливаюче вікно з переліком доступних макетів" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "Додати новий макет" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "Зберегти макети на диск. Некоректні зміни будуть втрачені!" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "Перезавантажити макети з диска, відкидаючи всі незбережені зміни." #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "Розширені / Експериментальні налаштування" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "Додати налаштування в основне вікно параметрів" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" "Заміна клавіатурних скорочень. Для того, щоб до вже існуючих додати нове " "скорочення, на етапі очікування введення, натисніть клавішу 'пробіл' чи " "'enter'." #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "Очистити клавіатурні скорочення" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "Спливаюче вікно мозаїки увімкнено " #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "Спливаюче вікно мозаїки вимкнено" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "Не визначено жодного коректного макета" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "Спливаюче вікно макетів: застосунок не знайдено" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "Пишіть тут для пошуку..." #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "Безіменний макет..." #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "'Режим редагування мозаїки' недоступний, коли відсутні видимі плитки" #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "Довідка" Tiling-Assistant-46/translations/zh_TW.po000066400000000000000000000426651457776040200206470ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-03-13 03:42+0100\n" "PO-Revision-Date: \n" "Last-Translator: laichiaheng\n" "Language-Team: None\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "X-Generator: Poedit 2.4.3\n" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:10 msgid "Report a Bug" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:14 msgid "User Guide" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:18 msgid "License" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:22 msgid "Changelog" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:26 msgid "Advanced..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:41 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:782 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1003 msgid "General" msgstr "一般" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:48 msgid "Tiling Popup" msgstr "模塊化彈出式選單" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:51 msgid "Open after tiling a window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:62 msgid "Include apps from all workspaces" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:83 msgid "Tile Groups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:86 msgid "Disable Tile Groups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:87 msgid "" "Tiled windows will no longer adapt their size to other tiled windows nor be " "raised or resized together. The Dynamic Keybinding Behavior 'Window Focus' " "and the Tiling Popup will also no longer work." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:102 msgid "Raise together" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:103 msgid "" "A tile group is created when a window gets tiled. If a tiled window is " "raised, raise the other windows of its tile group as well" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:114 msgid "App Switcher and Tiling Popup" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:115 msgid "" "This could conflict with other App Switcher (a.k.a. alt+Tab) extensions. You " "may need to re-enable this or the other extension after toggling this setting" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:135 msgid "Gaps" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:138 msgid "Windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:156 msgid "Screen Edges" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:178 msgid "Screen Edge Top" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:200 msgid "Screen Edge Left" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:222 msgid "Screen Edge Right" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:244 msgid "Screen Edge Bottom" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:266 msgid "Maximized Windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:282 msgid "Dynamic Keybinding Behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:283 msgid "" "The keybindings to maximize and tile to the top/bottom/left/right may change " "their behavior based on the window's tiling state" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:286 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:356 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:600 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:620 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:640 msgid "Disabled" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:287 msgid "Don't change the keybindings' behavior" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:296 msgid "Window Focus" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:297 msgid "" "Switch focus to the tiled window in the direction of the pressed shortcut" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:308 msgid "Tiling State" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:309 msgid "" "Adapt the tiling state to the pressed shortcut. For instance, a window tiled " "to the right half will tile to the bottom-right quarter, if 'tile to bottom' " "is activated" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:320 msgid "Tiling State (Windows)" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:321 msgid "" "Like 'Tiling State' but if the window isn't tiled or is already tiled to the " "bottom and the 'tile to bottom' shortcut is activated, minimize the window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:332 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:517 msgid "Favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:333 msgid "Move the window along your favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:353 msgid "Active Window Hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:357 msgid "Don't indicate the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:366 msgid "Minimal" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:367 msgid "" "Temporarily indicate the focused window when switching to a workspace with " "multiple non-overlapping windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:378 msgid "Always" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:379 msgid "" "Always indicate the focused window unless it's maximized or in fullscreen. " "There are issues on Wayland with GTK4 popups" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:398 msgid "Hint Color" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:399 msgid "The color of the frame indicating the focused window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:410 msgid "Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:411 msgid "" "The border size of the frame indicating the focused window for the always " "active hint" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:429 msgid "Inner Border Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:430 msgid "" "The border for the always active hint reaching inside the window frame. This " "is meant to cover rounded corners. However, GTK4 popups on Wayland will put " "the window behind the hint for whatever reason..." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:453 msgid "Animations" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:460 msgid "Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:471 msgid "Untiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:487 msgid "Default Window Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:488 msgid "The movement mode that is activated when no modifier key is pressed" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:495 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:849 msgid "Edge Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:496 msgid "" "Moving the window to the screen edges or corners will open the default tile " "preview" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:505 msgid "Adaptive Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:506 msgid "" "Releasing the grab on a window while hovering over a tile will push the " "overlapped window(s) aside" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:518 msgid "" "The tile preview will stick to your favorite layout from the 'Layouts' page" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:529 msgid "Ignore Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:530 msgid "Use Edge Tiling without Tiling Assistant's features" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:546 msgid "Other" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:549 msgid "Monitor Switch Grace Period" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:550 msgid "" "When a window is dragged to a new monitor the tile preview will stick to the " "old monitor for a very short time. This way you can tile windows by " "'throwing' it towards any screen edge even if a monitor is bordering that " "edge." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:561 msgid "Low Performance Movement Mode" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:562 msgid "" "Use this if there is a lag when moving windows around. This will however " "decrease the precision of the tile preview updates." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:577 msgid "Adapt 'Edge Tiling' to your Favorite Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:592 msgid "'Adaptive Tiling' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:601 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:621 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:641 msgid "Ctrl" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:602 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:622 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:642 msgid "Alt" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:603 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:623 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:643 msgid "RMB" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:604 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:624 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:644 msgid "Super" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:612 msgid "'Favorite Layout' Move Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:632 msgid "'Ignore Tiling Assistant' Mode Activator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:652 msgid "Vertical Edge Preview Trigger Area" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:675 msgid "Horizontal Edge Preview Trigger Area" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:698 msgid "Inverse Top Screen Edge Action Timer" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:721 msgid "Inverse Top Screen Edge Action for Landscape Displays" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:736 msgid "Inverse Top Screen Edge Action for Portrait Displays" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:751 msgid "Restore Window Size on" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:752 msgid "" "Tiled windows may not properly restore their size on Wayland. If that's the " "case, use 'Restore Window Size on Grab End'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:760 msgid "Grab Start" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:761 msgid "Grab End" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:775 msgid "Keybindings" msgstr "快捷鍵" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:785 msgid "Toggle 'Tiling Popup'" msgstr "切換至「彈出式選單」" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:790 msgid "Tile Editing Mode" msgstr "模塊編輯模式" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:791 msgid "A keyboard-driven mode to manage your tiled windows" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:796 msgid "Auto-Tile" msgstr "自動排版" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:797 msgid "Un/tile the current window based on the visible tiles" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:802 msgid "Toggle 'Always on Top'" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:811 msgid "Toggle Maximization" msgstr "切換至最大化" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:816 msgid "Toggle Vertical Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:825 msgid "Toggle Horizontal Maximization" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:834 msgid "Restore Window Size" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:839 msgid "Move Window to Center" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:852 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:912 msgid "Tile to top" msgstr "模塊化至上" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:857 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:917 msgid "Tile to bottom" msgstr "模塊化至下" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:862 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:922 msgid "Tile to left" msgstr "模塊化至左" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:867 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:927 msgid "Tile to right" msgstr "模塊化至右" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:877 msgid "Corner Tiling" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:880 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:944 msgid "Tile to top-left" msgstr "模塊化至左上" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:885 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:949 msgid "Tile to top-right" msgstr "模塊化至右上" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:890 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:954 msgid "Tile to bottom-left" msgstr "模塊化至左下" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:895 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:959 msgid "Tile to bottom-right" msgstr "模塊化至右下" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:905 msgid "Edge Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:937 msgid "Corner Tiling without Tiling Assistant" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:969 msgid "Debugging" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:976 msgid "Show Tiled Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:981 msgid "Show Free Screen Rects" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:992 #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1028 msgid "Layouts" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1006 msgid "Panel Indicator" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1017 msgid "Search for a Layout" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1018 msgid "Open a popup listing all the available layouts" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1052 msgid "Add a new Layout." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1059 msgid "Save the layouts to the disk. Invalid changes will be lost!" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1066 msgid "Reload the layouts from the disk - discarding all non-saved changes." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1123 msgid "Advanced / Experimental Settings" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/prefs.ui:1124 msgid "Show more settings in the main preference window" msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:11 msgid "" "Replace the keyboard shortcuts. Press 'space' or 'return' when listening for " "a shortcut to append a new one to the existing shortcuts instead." msgstr "" #: tiling-assistant@leleat-on-github/src/ui/shortcutListener.ui:23 msgid "Clear the keyboard shortcuts" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:56 msgid "Tiling popup enabled" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/keybindingHandler.js:57 msgid "Tiling popup was disabled" msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:104 #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:494 msgid "No valid layouts defined." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:195 msgid "Popup Layouts: App not found." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:338 msgid "Type to search..." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/layoutsManager.js:444 msgid "Nameless layout..." msgstr "" #: tiling-assistant@leleat-on-github/src/extension/tileEditingMode.js:61 msgid "Can't enter 'Tile Editing Mode', if no tiled window is visible." msgstr "" #: tiling-assistant@leleat-on-github/src/prefs/layoutRowEntry.js:37 msgid "'User Guide' for help..." msgstr "" #~ msgid "Window Gaps" #~ msgstr "視窗間距" #~ msgid "Gaps on Maximized Windows" #~ msgstr "最大化視窗的間距" #~ msgid " General " #~ msgstr " 一般 " #~ msgid " Side Tiling " #~ msgstr " 側邊排版 " #~ msgid " Corner Tiling " #~ msgstr " 角落排版 " #~ msgid "Tiling Assistant" #~ msgstr "協助排版" #~ msgid "Hidden Settings" #~ msgstr "隱藏設定" #~ msgid "Tiling Popup: Current Workspace only" #~ msgstr "模塊彈出式選單:僅限目前工作區" #~ msgid "Tile Editing Mode: Focus Color" #~ msgstr "模塊編輯模式:聚焦的顏色" #~ msgid "Tile Animations" #~ msgstr "模塊化動畫" #~ msgid "Untile Animations" #~ msgstr "解除模塊化動畫"