mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-03-24 02:20:09 +08:00
Merge pull request #16962 from lujun9972/add-MjAyMDAxMDggSG93IHRvIHNldHVwIG11bHRpcGxlIG1vbml0b3JzIGluIHN3YXkubWQK
自动选题: 20200108 How to setup multiple monitors in sway
This commit is contained in:
commit
be9ce16313
@ -0,0 +1,599 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Introduction to the Linux goto shell utility)
|
||||
[#]: via: (https://opensource.com/article/20/1/directories-autocomplete-linux)
|
||||
[#]: author: (Lazarus Lazaridis https://opensource.com/users/iridakos)
|
||||
|
||||
Introduction to the Linux goto shell utility
|
||||
======
|
||||
Learn how to use goto to alias and navigate to directories with
|
||||
autocomplete in Linux.
|
||||
![Files in a folder][1]
|
||||
|
||||
The goto shell utility allows users to navigate to aliased directories and also supports autocompletion.
|
||||
|
||||
## How it works
|
||||
|
||||
Before you can use goto, you need to register your directory aliases. For example:
|
||||
|
||||
|
||||
```
|
||||
`goto -r dev /home/iridakos/development`
|
||||
```
|
||||
|
||||
then change to that directory, e.g.:
|
||||
|
||||
|
||||
```
|
||||
`goto dev`
|
||||
```
|
||||
|
||||
![goto demo][2]
|
||||
|
||||
## Autocompletion in goto
|
||||
|
||||
**goto** comes with a nice autocompletion script—whenever you press the Tab key after the **goto** command, Bash or Zsh will prompt you with suggestions of the aliases that are available:
|
||||
|
||||
|
||||
```
|
||||
$ goto <tab>
|
||||
bc /etc/bash_completion.d
|
||||
dev /home/iridakos/development
|
||||
rubies /home/iridakos/.rvm/rubies
|
||||
```
|
||||
|
||||
## Installing goto
|
||||
|
||||
There are several ways to install goto.
|
||||
|
||||
### Via script
|
||||
|
||||
Clone the repository and run the install script as a superuser or root:
|
||||
|
||||
|
||||
```
|
||||
git clone <https://github.com/iridakos/goto.git>
|
||||
cd goto
|
||||
sudo ./install
|
||||
```
|
||||
|
||||
### Manually
|
||||
|
||||
Copy the file **goto.sh** somewhere in your filesystem and add a line in your **.zshrc** or **.bashrc** to source it.
|
||||
|
||||
For example, if you placed the file in your home folder, all you have to do is add the following line to your **.zshrc** or **.bashrc** file:
|
||||
|
||||
|
||||
```
|
||||
`source ~/goto.sh`
|
||||
```
|
||||
|
||||
### MacOS Homebrew
|
||||
|
||||
A formula named **goto** is available for the Bash shell in MacOS:
|
||||
|
||||
|
||||
```
|
||||
`brew install goto`
|
||||
```
|
||||
|
||||
### Add colored output
|
||||
|
||||
|
||||
```
|
||||
`echo -e "\$include /etc/inputrc\nset colored-completion-prefix on" >> ~/.inputrc`
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
|
||||
* You need to restart your shell after installation.
|
||||
* You need to have the Bash completion feature enabled for Bash in MacOS (see this [issue][3]).
|
||||
* You can install it with **brew install bash-completion** if you don't have it enabled.
|
||||
|
||||
|
||||
|
||||
## Ways to use goto
|
||||
|
||||
### Change to an aliased directory
|
||||
|
||||
To change to an aliased directory, type:
|
||||
|
||||
|
||||
```
|
||||
`goto <alias>`
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
|
||||
```
|
||||
`goto dev`
|
||||
```
|
||||
|
||||
### Register an alias
|
||||
|
||||
To register a directory alias, type:
|
||||
|
||||
|
||||
```
|
||||
`goto -r <alias> <directory>`
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
|
||||
```
|
||||
`goto --register <alias> <directory>`
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
|
||||
```
|
||||
`goto -r blog /mnt/external/projects/html/blog`
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
|
||||
```
|
||||
`goto --register blog /mnt/external/projects/html/blog`
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
|
||||
* **goto** **expands** the directories, so you can easily alias your current directory with the following command and it will automatically be aliased to the whole path: [code]`goto -r last_release .`
|
||||
```
|
||||
* Pressing the Tab key after the alias name provides the shell's default directory suggestions.
|
||||
|
||||
|
||||
|
||||
### Unregister an alias
|
||||
|
||||
To unregister an alias, use:
|
||||
```
|
||||
`goto -u <alias>`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --unregister <alias>`
|
||||
```
|
||||
For example:
|
||||
```
|
||||
`goto -u last_release`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --unregister last_release`
|
||||
```
|
||||
**Note:** By pressing the Tab key after the command (**-u** or **\--unregister**), the completion script will prompt you with the list of registered aliases.
|
||||
|
||||
### List aliases
|
||||
|
||||
To get a list of your currently registered aliases, use:
|
||||
```
|
||||
`goto -l`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --list`
|
||||
```
|
||||
### Expand an alias
|
||||
|
||||
To expand an alias to its value, use:
|
||||
```
|
||||
`goto -x <alias>`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --expand <alias>`
|
||||
```
|
||||
For example:
|
||||
```
|
||||
`goto -x last_release`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --expand last_release`
|
||||
```
|
||||
### Clean up aliases
|
||||
|
||||
To clean up the aliases from directories that are no longer accessible in your filesystem, use:
|
||||
```
|
||||
`goto -c`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --cleanup`
|
||||
```
|
||||
### Get help
|
||||
|
||||
To view the tool's help information, use:
|
||||
```
|
||||
`goto -h`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --help`
|
||||
```
|
||||
### Check the version
|
||||
|
||||
To view the tool's version, use:
|
||||
```
|
||||
`goto -v`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --version`
|
||||
```
|
||||
### Push before changing directories
|
||||
|
||||
To push the current directory onto the directory stack before changing directories, type:
|
||||
```
|
||||
`goto -p <alias>`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --push <alias>`
|
||||
```
|
||||
### Revert to a pushed directory
|
||||
|
||||
To return to a pushed directory, type:
|
||||
```
|
||||
`goto -o`
|
||||
```
|
||||
or
|
||||
```
|
||||
`goto --pop`
|
||||
```
|
||||
**Note:** This command is equivalent to **popd** but within the **goto** command.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you see the error **command not found: compdef** in Zsh, it means you need to load **bashcompinit**. To do so, append this to your **.zshrc** file:
|
||||
```
|
||||
|
||||
|
||||
autoload bashcompinit
|
||||
bashcompinit
|
||||
|
||||
```
|
||||
## Get involved
|
||||
|
||||
The goto tool is open source under the [MIT License][4] terms, and contributions are welcomed. To learn more, visit the [Contributing][5] section in goto's GitHub repository.
|
||||
|
||||
## The goto script
|
||||
```
|
||||
|
||||
|
||||
goto()
|
||||
{
|
||||
local target
|
||||
_goto_resolve_db
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
# display usage and exit when no args
|
||||
_goto_usage
|
||||
return
|
||||
fi
|
||||
|
||||
subcommand="$1"
|
||||
shift
|
||||
case "$subcommand" in
|
||||
-c|--cleanup)
|
||||
_goto_cleanup "$@"
|
||||
;;
|
||||
-r|--register) # Register an alias
|
||||
_goto_register_alias "$@"
|
||||
;;
|
||||
-u|--unregister) # Unregister an alias
|
||||
_goto_unregister_alias "$@"
|
||||
;;
|
||||
-p|--push) # Push the current directory onto the pushd stack, then goto
|
||||
_goto_directory_push "$@"
|
||||
;;
|
||||
-o|--pop) # Pop the top directory off of the pushd stack, then change that directory
|
||||
_goto_directory_pop
|
||||
;;
|
||||
-l|--list)
|
||||
_goto_list_aliases
|
||||
;;
|
||||
-x|--expand) # Expand an alias
|
||||
_goto_expand_alias "$@"
|
||||
;;
|
||||
-h|--help)
|
||||
_goto_usage
|
||||
;;
|
||||
-v|--version)
|
||||
_goto_version
|
||||
;;
|
||||
*)
|
||||
_goto_directory "$subcommand"
|
||||
;;
|
||||
esac
|
||||
return $?
|
||||
}
|
||||
|
||||
_goto_resolve_db()
|
||||
{
|
||||
GOTO_DB="${GOTO_DB:-$HOME/.goto}"
|
||||
touch -a "$GOTO_DB"
|
||||
}
|
||||
|
||||
_goto_usage()
|
||||
{
|
||||
cat <<\USAGE
|
||||
usage: goto [<option>] <alias> [<directory>]
|
||||
|
||||
default usage:
|
||||
goto <alias> \- changes to the directory registered for the given alias
|
||||
|
||||
OPTIONS:
|
||||
-r, --register: registers an alias
|
||||
goto -r|--register <alias> <directory>
|
||||
-u, --unregister: unregisters an alias
|
||||
goto -u|--unregister <alias>
|
||||
-p, --push: pushes the current directory onto the stack, then performs goto
|
||||
goto -p|--push <alias>
|
||||
-o, --pop: pops the top directory from the stack, then changes to that directory
|
||||
goto -o|--pop
|
||||
-l, --list: lists aliases
|
||||
goto -l|--list
|
||||
-x, --expand: expands an alias
|
||||
goto -x|--expand <alias>
|
||||
-c, --cleanup: cleans up non existent directory aliases
|
||||
goto -c|--cleanup
|
||||
-h, --help: prints this help
|
||||
goto -h|--help
|
||||
-v, --version: displays the version of the goto script
|
||||
goto -v|--version
|
||||
USAGE
|
||||
}
|
||||
|
||||
# Displays version
|
||||
_goto_version()
|
||||
{
|
||||
echo "goto version 1.2.4.1"
|
||||
}
|
||||
|
||||
# Expands directory.
|
||||
# Helpful for ~, ., .. paths
|
||||
_goto_expand_directory()
|
||||
{
|
||||
builtin cd "$1" 2>/dev/null && pwd
|
||||
}
|
||||
|
||||
# Lists registered aliases.
|
||||
_goto_list_aliases()
|
||||
{
|
||||
local IFS=$' '
|
||||
if [ -f "$GOTO_DB" ]; then
|
||||
while read -r name directory; do
|
||||
printf '\e[1;36m%20s \e[0m%s\n' "$name" "$directory"
|
||||
done < "$GOTO_DB"
|
||||
else
|
||||
echo "You haven't configured any directory aliases yet."
|
||||
fi
|
||||
}
|
||||
|
||||
# Expands a registered alias.
|
||||
_goto_expand_alias()
|
||||
{
|
||||
if [ "$#" -ne "1" ]; then
|
||||
_goto_error "usage: goto -x|--expand <alias>"
|
||||
return
|
||||
fi
|
||||
|
||||
local resolved
|
||||
|
||||
resolved=$(_goto_find_alias_directory "$1")
|
||||
if [ -z "$resolved" ]; then
|
||||
_goto_error "alias '$1' does not exist"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "$resolved"
|
||||
}
|
||||
|
||||
# Lists duplicate directory aliases
|
||||
_goto_find_duplicate()
|
||||
{
|
||||
local duplicates=
|
||||
|
||||
duplicates=$(sed -n 's:[^ ]* '"$1"'$:&:p' "$GOTO_DB" 2>/dev/null)
|
||||
echo "$duplicates"
|
||||
}
|
||||
|
||||
# Registers and alias.
|
||||
_goto_register_alias()
|
||||
{
|
||||
if [ "$#" -ne "2" ]; then
|
||||
_goto_error "usage: goto -r|--register <alias> <directory>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! [[ $1 =~ ^[[:alnum:]]+[a-zA-Z0-9_-]*$ ]]; then
|
||||
_goto_error "invalid alias - can start with letters or digits followed by letters, digits, hyphens or underscores"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local resolved
|
||||
resolved=$(_goto_find_alias_directory "$1")
|
||||
|
||||
if [ -n "$resolved" ]; then
|
||||
_goto_error "alias '$1' exists"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local directory
|
||||
directory=$(_goto_expand_directory "$2")
|
||||
if [ -z "$directory" ]; then
|
||||
_goto_error "failed to register '$1' to '$2' - can't cd to directory"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local duplicate
|
||||
duplicate=$(_goto_find_duplicate "$directory")
|
||||
if [ -n "$duplicate" ]; then
|
||||
_goto_warning "duplicate alias(es) found: \\\n$duplicate"
|
||||
fi
|
||||
|
||||
# Append entry to file.
|
||||
echo "$1 $directory" >> "$GOTO_DB"
|
||||
echo "Alias '$1' registered successfully."
|
||||
}
|
||||
|
||||
# Unregisters the given alias.
|
||||
_goto_unregister_alias()
|
||||
{
|
||||
if [ "$#" -ne "1" ]; then
|
||||
_goto_error "usage: goto -u|--unregister <alias>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local resolved
|
||||
resolved=$(_goto_find_alias_directory "$1")
|
||||
if [ -z "$resolved" ]; then
|
||||
_goto_error "alias '$1' does not exist"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
local readonly GOTO_DB_TMP="$HOME/.goto_"
|
||||
# Delete entry from file.
|
||||
sed "/^$1 /d" "$GOTO_DB" > "$GOTO_DB_TMP" && mv "$GOTO_DB_TMP" "$GOTO_DB"
|
||||
echo "Alias '$1' unregistered successfully."
|
||||
}
|
||||
|
||||
# Pushes the current directory onto the stack, then goto
|
||||
_goto_directory_push()
|
||||
{
|
||||
if [ "$#" -ne "1" ]; then
|
||||
_goto_error "usage: goto -p|--push <alias>"
|
||||
return
|
||||
fi
|
||||
|
||||
{ pushd . || return; } 1>/dev/null 2>&1
|
||||
|
||||
_goto_directory "$@"
|
||||
}
|
||||
|
||||
# Pops the top directory from the stack, then goto
|
||||
_goto_directory_pop()
|
||||
{
|
||||
{ popd || return; } 1>/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Unregisters aliases whose directories no longer exist.
|
||||
_goto_cleanup()
|
||||
{
|
||||
if ! [ -f "$GOTO_DB" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
while IFS= read -r i && [ -n "$i" ]; do
|
||||
echo "Cleaning up: $i"
|
||||
_goto_unregister_alias "$i"
|
||||
done <<< "$(awk '{al=$1; $1=""; dir=substr($0,2);
|
||||
system("[ ! -d \"" dir "\" ] && echo " al)}' "$GOTO_DB")"
|
||||
}
|
||||
|
||||
# Changes to the given alias' directory
|
||||
_goto_directory()
|
||||
{
|
||||
local target
|
||||
|
||||
target=$(_goto_resolve_alias "$1") || return 1
|
||||
|
||||
builtin cd "$target" 2> /dev/null || \
|
||||
{ _goto_error "Failed to goto '$target'" && return 1; }
|
||||
}
|
||||
|
||||
# Fetches the alias directory.
|
||||
_goto_find_alias_directory()
|
||||
{
|
||||
local resolved
|
||||
|
||||
resolved=$(sed -n "s/^$1 \\\\(.*\\\\)/\\\1/p" "$GOTO_DB" 2>/dev/null)
|
||||
echo "$resolved"
|
||||
}
|
||||
|
||||
# Displays the given error.
|
||||
# Used for common error output.
|
||||
_goto_error()
|
||||
{
|
||||
(>&2 echo -e "goto error: $1")
|
||||
}
|
||||
|
||||
# Displays the given warning.
|
||||
# Used for common warning output.
|
||||
_goto_warning()
|
||||
{
|
||||
(>&2 echo -e "goto warning: $1")
|
||||
}
|
||||
|
||||
# Displays entries with aliases starting as the given one.
|
||||
_goto_print_similar()
|
||||
{
|
||||
local similar
|
||||
|
||||
similar=$(sed -n "/^$1[^ ]* .*/p" "$GOTO_DB" 2>/dev/null)
|
||||
if [ -n "$similar" ]; then
|
||||
(>&2 echo "Did you mean:")
|
||||
(>&2 column -t <<< "$similar")
|
||||
fi
|
||||
}
|
||||
|
||||
# Fetches alias directory, errors if it doesn't exist.
|
||||
_goto_resolve_alias()
|
||||
{
|
||||
local resolved
|
||||
|
||||
resolved=$(_goto_find_alias_directory "$1")
|
||||
|
||||
if [ -z "$resolved" ]; then
|
||||
_goto_error "unregistered alias $1"
|
||||
_goto_print_similar "$1"
|
||||
return 1
|
||||
else
|
||||
echo "${resolved}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Completes the goto function with the available commands
|
||||
_complete_goto_commands()
|
||||
{
|
||||
local IFS=$' \t\n'
|
||||
|
||||
# shellcheck disable=SC2207
|
||||
COMPREPLY=($(compgen -W "-r --register -u --unregister -p --push -o --pop -l --list -x --expand -c --cleanup -v --version" -- "$1"))
|
||||
}
|
||||
|
||||
# Completes the goto function with the available aliases
|
||||
_complete_goto_aliases()
|
||||
{
|
||||
local IFS=$'\n' matches
|
||||
_goto_resolve_db
|
||||
|
||||
# shellcheck disable=SC2207
|
||||
matches=($(sed -n "/^$1/p" "$GOTO_DB" 2>/dev/null))
|
||||
|
||||
if [ "${#matches[@]}" -eq "1" ]; then
|
||||
# remove the filenames attribute from the completion method
|
||||
compopt +o filenames 2>/dev/null
|
||||
|
||||
# if you find only one alias don't append the directory
|
||||
COMPREPLY=("${matches[0]// *}")
|
||||
else
|
||||
for i in "${!matches[@]}"; do
|
||||
# remove the filenames attribute from the completion method
|
||||
compopt +o filenames 2>/dev/null
|
||||
|
||||
if ! [[ $(uname -s) =~ Darwin* ]]; then
|
||||
matches[$i]=$(printf '%*s' "-$COLUMNS" "${matches[$i]}")
|
||||
|
||||
COMPREPLY+=("$(compgen -W "${matches[$i]}")")
|
||||
els
|
@ -0,0 +1,85 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to setup multiple monitors in sway)
|
||||
[#]: via: (https://fedoramagazine.org/how-to-setup-multiple-monitors-in-sway/)
|
||||
[#]: author: (arte219 https://fedoramagazine.org/author/arte219/)
|
||||
|
||||
How to setup multiple monitors in sway
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
Sway is a tiling Wayland compositor which has mostly the same features, look and workflow as the [i3 X11 window manager][2]. Because Sway uses Wayland instead of X11, the tools to setup X11 don’t always work in sway. This includes tools like _xrandr_, which are used in X11 window managers or desktops to setup monitors. This is why monitors have to be setup by editing the sway config file, and that’s what this article is about.
|
||||
|
||||
## **Getting your monitor ID’s**
|
||||
|
||||
First, you have to get the names sway uses to refer to your monitors. You can do this by running:
|
||||
|
||||
```
|
||||
$ swaymsg -t get_outputs
|
||||
```
|
||||
|
||||
You will get information about all of your monitors, every monitor separated by an empty line.
|
||||
|
||||
You have to look for the first line of every section, and for what’s after “Output”. For example, when you see a line like “_Output DVI-D-1 ‘Philips Consumer Electronics Company’_”, the output ID is “DVI-D-1”. Note these ID’s and which physical monitors they belong to.
|
||||
|
||||
## **Editing the config file**
|
||||
|
||||
If you haven’t edited the Sway config file before, you have to copy it to your home directory by running this command:
|
||||
|
||||
```
|
||||
cp -r /etc/sway/config ~/.config/sway/config
|
||||
```
|
||||
|
||||
Now the default config file is located in _~/.config/sway_ and called “config”. You can edit it using any text editor.
|
||||
|
||||
Now you have to do a little bit of math. Imagine a grid with the origin in the top left corner. The units of the X and Y coordinates are pixels. The Y axis is inverted. This means that if you, for example, start at the origin and you move 100 pixels to the right and 80 pixels down, your coordinates will be (100, 80).
|
||||
|
||||
You have to calculate where your displays are going to end up on this grid. The locations of the displays are specified with the top left pixel. For example, if we want to have a monitor with name HDMI1 and a resolution of 1920×1080, and to the right of it a laptop monitor with name eDP1 and a resolution of 1600×900, you have to type this in your config file:
|
||||
|
||||
```
|
||||
output HDMI1 pos 0 0
|
||||
output eDP1 pos 1920 0
|
||||
```
|
||||
|
||||
You can also specify the resolutions manually by using the _res_ option:
|
||||
|
||||
```
|
||||
output HDMI1 pos 0 0 res 1920x1080
|
||||
output eDP1 pos 1920 0 res 1600x900
|
||||
```
|
||||
|
||||
## **Binding workspaces to monitors**
|
||||
|
||||
Using sway with multiple monitors can be a little bit tricky with workspace management. Luckily, you can bind workspaces to a specific monitor, so you can easily switch to that monitor and use your displays more efficiently. This can simply be done by the workspace command in your config file. For example, if you want to bind workspace 1 and 2 to monitor DVI-D-1 and workspace 8 and 9 to monitor HDMI-A-1, you can do that by using:
|
||||
|
||||
```
|
||||
workspace 1 output DVI-D-1
|
||||
workspace 2 output DVI-D-1
|
||||
```
|
||||
|
||||
```
|
||||
workspace 8 output HDMI-A-1
|
||||
workspace 9 output HDMI-A-1
|
||||
```
|
||||
|
||||
That’s it! These are the basics of multi monitor setup in sway. A more detailed guide can be found at <https://github.com/swaywm/sway/wiki#Multihead>.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/how-to-setup-multiple-monitors-in-sway/
|
||||
|
||||
作者:[arte219][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/arte219/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2020/01/sway-multiple-monitors-816x345.png
|
||||
[2]: https://fedoramagazine.org/getting-started-i3-window-manager/
|
Loading…
Reference in New Issue
Block a user