Sway support removed. Moved I38 specific scripts out of the branch covered by dex.
This commit is contained in:
@@ -84,6 +84,39 @@ Bypass mode passes all keys directly to the application, which is useful for app
|
||||
|
||||
*GNOME/MATE comparison:* In GNOME/MATE, applications always receive keyboard input directly. Bypass mode simulates this behavior within i3.
|
||||
|
||||
## Personal Mode
|
||||
|
||||
Personal Mode is a user-defined mode for adding your own keybindings that will not be overwritten when you regenerate your I38 configuration.
|
||||
|
||||
### Entering Personal Mode
|
||||
|
||||
When you first run I38, you are prompted to choose a personal mode key. If you selected one, press that key to enter Personal Mode.
|
||||
|
||||
### Adding Custom Bindings
|
||||
|
||||
To add your own shortcuts, edit the file `~/.config/i3/customizations`. This file is never overwritten by I38.
|
||||
|
||||
Inside the `mode "personal" { ... }` block, you can add any i3 `bindsym` commands. Be sure to end each binding with `, mode "default"` so that Personal Mode exits after the action.
|
||||
|
||||
Example:
|
||||
|
||||
```i3
|
||||
mode "personal" {
|
||||
bindsym f exec firefox, mode "default"
|
||||
bindsym Shift+f exec firefox --private-window, mode "default"
|
||||
bindsym Escape mode "default"
|
||||
bindsym Control+g mode "default"
|
||||
}
|
||||
```
|
||||
|
||||
In this example, pressing your personal mode key followed by `f` launches Firefox, and `Shift+f` launches a private Firefox window.
|
||||
|
||||
### Default Personal Mode Bindings
|
||||
|
||||
By default, Personal Mode includes:
|
||||
- `F1` | Show personal mode keybindings
|
||||
- `Escape` or `Control` + `g` | Exit Personal Mode without taking action
|
||||
|
||||
## Panel Mode
|
||||
|
||||
Panel Mode provides quick access to information displays and utility panels. To enter Panel Mode, press `Alt` + `Control` + `Tab`. A distinctive sound will play when Panel Mode is active.
|
||||
@@ -100,6 +133,10 @@ In Panel Mode, single keypresses launch different information panels:
|
||||
| `r` | Open reminder panel |
|
||||
| `n` | Launch notes application |
|
||||
| `b` | Open bluetooth. *requires blueman be installed at the time of your i3 config generation* |
|
||||
| `Shift` + `b` | Show detailed battery information |
|
||||
| `m` | Launch password manager |
|
||||
| `p` | Show power options |
|
||||
| `Control` + `MODKEY` + `l` | Lock screen *(if screen lock PIN is configured)* |
|
||||
| `Escape` or `Control` + `g` | Exit Panel Mode without taking action |
|
||||
|
||||
Just like Ratpoison Mode, Panel Mode automatically returns you to Default Mode after a selection is made or when you press Escape/Control+g to cancel.
|
||||
|
||||
@@ -187,124 +187,35 @@ The AI assistant stores its configuration in `~/.config/stormux/I38/ai.conf` usi
|
||||
**Ollama**: Requires Ollama service to be running locally. Automatically discovers available models and supports text analysis.
|
||||
|
||||
|
||||
## Custom Applications in Ratpoison Mode
|
||||
## Personal Mode
|
||||
|
||||
I38 now includes a powerful system for adding custom applications to ratpoison mode with user-defined keybindings. During the configuration process, after setting up window event sounds, you'll be prompted to add custom applications that will be accessible through ratpoison mode.
|
||||
Personal Mode is a user-defined mode where you can add your own keybindings without worrying about them being overwritten when you update I38.
|
||||
|
||||
### How It Works
|
||||
### Setup
|
||||
|
||||
The system will prompt you through a series of questions for each application you want to add:
|
||||
When you run `i38.sh`, you are prompted to choose a personal mode key (or you can skip it). If you selected one, pressing that key enters Personal Mode.
|
||||
|
||||
1. **Application Name**: A descriptive name for the application
|
||||
2. **Execution Command**: The full path or command to run the application
|
||||
3. **Command Flags**: Optional command-line arguments
|
||||
4. **Keybinding**: A custom key combination using I38's notation system
|
||||
### Adding Custom Bindings
|
||||
|
||||
### Keybinding Notation System
|
||||
Edit `~/.config/i3/customizations` to add your own shortcuts. This file is never overwritten by I38. Inside the `mode "personal" { ... }` block, add i3 `bindsym` commands and end each one with `, mode "default"` so the mode exits after the action.
|
||||
|
||||
I38 uses a simple notation system to define keybindings that supports modifiers and special keys:
|
||||
Example:
|
||||
|
||||
#### Modifiers
|
||||
- `^` = Control (Ctrl)
|
||||
- `!` = Alt
|
||||
- `#` = Super (Windows/Cmd key)
|
||||
- `m` = Your chosen mod key (configured during setup)
|
||||
- Uppercase letters automatically add Shift (e.g., `C` = Shift+c)
|
||||
|
||||
#### Special Keys
|
||||
- **Function Keys**: `f1`, `f2`, ... `f12`
|
||||
- **Arrow Keys**: `up`, `down`, `left`, `right`
|
||||
- **Navigation Keys**: `home`, `end`, `pageup`, `pagedown`
|
||||
- **Editing Keys**: `insert`, `delete`, `backspace`
|
||||
- **Other Keys**: `space`, `tab`, `return`, `escape`, `print`
|
||||
|
||||
#### Example Keybindings
|
||||
- `c` = Just the 'c' key
|
||||
- `^c` = Control+c
|
||||
- `!f1` = Alt+F1
|
||||
- `mspace` = Your mod key + Space
|
||||
- `^!up` = Control+Alt+Up arrow
|
||||
- `#pagedown` = Super+Page Down
|
||||
- `C` = Shift+c
|
||||
- `^C` = Control+Shift+c
|
||||
|
||||
### Example Configuration Session
|
||||
|
||||
Here's what the configuration prompts look like:
|
||||
|
||||
```
|
||||
Enter application name (or press enter when finished): Discord
|
||||
Enter execution path/command for Discord: discord
|
||||
Enter command line flags for Discord (optional): --no-sandbox
|
||||
Enter keybinding for Discord (Examples: c, ^c, !f1, mspace, ^!up) or ? for help: d
|
||||
```i3
|
||||
mode "personal" {
|
||||
bindsym f exec firefox, mode "default"
|
||||
bindsym Shift+f exec firefox --private-window, mode "default"
|
||||
bindsym Escape mode "default"
|
||||
bindsym Control+g mode "default"
|
||||
}
|
||||
```
|
||||
|
||||
Another example:
|
||||
```
|
||||
Enter application name (or press enter when finished): Terminal Calculator
|
||||
Enter execution path/command for Terminal Calculator: gnome-calculator
|
||||
Enter command line flags for Terminal Calculator (optional):
|
||||
Enter keybinding for Terminal Calculator (Examples: c, ^c, !f1, mspace, ^!up) or ? for help: ^#c
|
||||
```
|
||||
With this example, pressing your personal mode key followed by `f` opens Firefox. `Shift+f` opens a private window.
|
||||
|
||||
### Getting Help During Configuration
|
||||
|
||||
If you type `?` when prompted for a keybinding, I38 will display a comprehensive help screen with:
|
||||
- Complete modifier notation reference
|
||||
- List of all supported special keys
|
||||
- Multiple examples of different keybinding combinations
|
||||
- Rules about uppercase letters and Shift
|
||||
|
||||
### Conflict Detection
|
||||
|
||||
I38 automatically prevents keybinding conflicts by:
|
||||
- Maintaining a list of all existing ratpoison mode bindings
|
||||
- Checking your custom keybinding against reserved keys
|
||||
- Showing an error message if you try to use a taken keybinding
|
||||
- Asking you to choose a different key combination
|
||||
|
||||
### Reserved Keybindings
|
||||
|
||||
The following keys are already used in ratpoison mode and cannot be assigned to custom applications:
|
||||
|
||||
- `c` = Terminal
|
||||
- `e` = Text editor
|
||||
- `f` = File manager
|
||||
- `w` = Web browser
|
||||
- `k` = Kill window
|
||||
- `m` = Mumble (if installed)
|
||||
- `p` = Pidgin (if installed)
|
||||
- `g` = Game controller status
|
||||
- Various modifier combinations for volume, music controls, etc.
|
||||
|
||||
### Using Your Custom Applications
|
||||
|
||||
Once configured, access your custom applications by:
|
||||
1. Press your ratpoison mode key (e.g., Alt+Escape)
|
||||
2. Press your custom keybinding (e.g., `d` for Discord)
|
||||
3. The application launches and ratpoison mode exits
|
||||
|
||||
### Advanced Examples
|
||||
|
||||
**Media Applications:**
|
||||
- `vlc` bound to `v` for VLC media player
|
||||
- `spotify` bound to `^s` for Spotify with Control+s
|
||||
|
||||
**Development Tools:**
|
||||
- `code` bound to `mf2` for VS Code with mod+F2
|
||||
- `gimp` bound to `!g` for GIMP with Alt+g
|
||||
|
||||
**System Tools:**
|
||||
- `htop` bound to `^#h` for system monitor with Control+Super+h
|
||||
- `pavucontrol` bound to `!space` for audio control with Alt+Space
|
||||
|
||||
### Tips for Choosing Keybindings
|
||||
|
||||
1. **Keep it memorable**: Use the first letter of the application name when possible
|
||||
2. **Group related apps**: Use similar modifiers for related applications
|
||||
3. **Consider frequency**: Use simpler keys for frequently used applications
|
||||
4. **Avoid conflicts**: The system will warn you, but plan ahead for a logical layout
|
||||
### Default Bindings
|
||||
|
||||
- `F1` — Show personal mode keybindings
|
||||
- `Escape` or `Control+g` — Exit Personal Mode
|
||||
|
||||
## Panel Mode
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
# 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 <https://www.gnu.org/licenses/>.
|
||||
# Flag for sway configurations
|
||||
usingSway=1 # Not by default.
|
||||
i3Path="${XDG_CONFIG_HOME:-$HOME/.config}/i3"
|
||||
i3msg="i3-msg"
|
||||
configFile="${PWD}/I38_preferences.conf"
|
||||
@@ -527,7 +525,6 @@ EOF
|
||||
# Array of command line arguments
|
||||
declare -A command=(
|
||||
[h]="This help screen."
|
||||
[s]="Create sway configuration instead of i3."
|
||||
[u]="Copy over the latest version of scripts."
|
||||
[x]="Generate ~/.xinitrc and ~/.xprofile."
|
||||
[X]="Generate ~/.xprofile only."
|
||||
@@ -539,12 +536,6 @@ args="${args//[[:space:]]/}"
|
||||
while getopts "${args}" i ; do
|
||||
case "$i" in
|
||||
h) help;;
|
||||
s)
|
||||
swaySystemIncludesPath="/etc/sway/config.d"
|
||||
usingSway=0
|
||||
i3msg="swaymsg"
|
||||
i3Path="${XDG_CONFIG_HOME:-$HOME/.config}/sway"
|
||||
;;
|
||||
u) update_scripts;;
|
||||
x) write_xinitrc ;&
|
||||
X) write_xprofile ;;
|
||||
@@ -879,15 +870,6 @@ cat << EOF > "${i3Path}/config"
|
||||
# $(date '+%A, %B %d, %Y at %I:%M%p')
|
||||
EOF
|
||||
|
||||
# If we are using Sway, we need to load in the system configuration
|
||||
# Usually, this is for system specific dBus things that the distro knows how to manage; we should trust their judgment with that
|
||||
if [[ $usingSway ]] && [[ -d "${swaySystemIncludesPath}" ]]; then
|
||||
cat << EOF >> "${i3Path}/config"
|
||||
# Include your distribution Sway configuration files.
|
||||
include ${swaySystemIncludesPath}/*
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat << EOF >> "${i3Path}/config"
|
||||
# i3 config file (v4)
|
||||
#
|
||||
@@ -1211,16 +1193,10 @@ bindsym Shift+c exec $(command -v cthulhu) --replace, mode "default"
|
||||
bindsym Shift+o exec $(command -v orca) --replace, mode "default"
|
||||
# Toggle screen reader
|
||||
bindsym Shift+t exec ${i3Path}/scripts/toggle_screenreader.sh, mode "default"
|
||||
$(if [[ $usingSway -eq 0 ]]; then
|
||||
echo "# reload the configuration file"
|
||||
echo "bindsym Control+semicolon exec bash -c '$i3msg -t command reload && spd-say -P important -Cw \"I38 Configuration reloaded.\"', mode \"default\""
|
||||
|
||||
else
|
||||
echo "# reload the configuration file"
|
||||
echo "bindsym Control+semicolon exec bash -c '$i3msg -t run_command reload && spd-say -P important -Cw \"I38 Configuration reloaded.\"', mode \"default\""
|
||||
echo "# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)"
|
||||
echo "bindsym Control+Shift+semicolon exec $i3msg -t run_command restart && spd-say -P important -Cw \"I3 restarted.\", mode \"default\""
|
||||
fi)
|
||||
# reload the configuration file
|
||||
bindsym Control+semicolon exec bash -c '$i3msg -t run_command reload && spd-say -P important -Cw "I38 Configuration reloaded."', mode "default"
|
||||
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
|
||||
bindsym Control+Shift+semicolon exec $i3msg -t run_command restart && spd-say -P important -Cw "I3 restarted.", mode "default"
|
||||
# Run dialog with exclamation
|
||||
bindsym Shift+exclam exec ${i3Path}/scripts/run_dialog.sh, mode "default"
|
||||
# exit i3 (logs you out of your X session)
|
||||
@@ -1239,50 +1215,28 @@ fi
|
||||
cat << EOF >> "${i3Path}/config"
|
||||
# Auto start section
|
||||
$(if [[ $sounds -eq 0 ]]; then
|
||||
if [[ $usingSway -eq 0 ]]; then
|
||||
echo "exec --no-startup-id ${i3Path}/scripts/sound.py"
|
||||
else
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/sound.py"
|
||||
fi
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/sound.py"
|
||||
fi
|
||||
# Steam game focus handler (i3 only) - focuses games when they open behind Big Picture
|
||||
if [[ $usingSway -ne 0 ]] && command -v steam &> /dev/null; then
|
||||
# Steam game focus handler - focuses games when they open behind Big Picture
|
||||
if command -v steam &> /dev/null; then
|
||||
echo "exec --no-startup-id ${i3Path}/scripts/steam_games.py"
|
||||
fi
|
||||
# i3 watchdog - monitors i3 responsiveness and auto-recovers from freezes
|
||||
if [[ $usingSway -ne 0 ]]; then
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/i3_watchdog.sh"
|
||||
fi
|
||||
# xbrlapi is X11-only, skip on Sway/Wayland
|
||||
if [[ $brlapi -eq 0 ]] && [[ $usingSway -ne 0 ]]; then
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/i3_watchdog.sh"
|
||||
if [[ $brlapi -eq 0 ]]; then
|
||||
echo 'exec --no-startup-id xbrlapi --quiet'
|
||||
fi
|
||||
if [[ $udiskie -eq 0 ]]; then
|
||||
echo 'exec --no-startup-id udiskie'
|
||||
fi
|
||||
# Notification daemon
|
||||
if [[ $usingSway -eq 0 ]]; then
|
||||
# Sway: prefer Wayland-native notification daemons
|
||||
if command -v mako &> /dev/null; then
|
||||
echo 'exec_always --no-startup-id mako'
|
||||
elif [[ -x "/usr/lib/xfce4/notifyd/xfce4-notifyd" ]]; then
|
||||
# Fallback to X11 variant via XWayland
|
||||
echo 'exec_always --no-startup-id /usr/lib/xfce4/notifyd/xfce4-notifyd'
|
||||
elif [[ -x "/usr/lib/notification-daemon-1.0/notification-daemon" ]]; then
|
||||
echo 'exec_always --no-startup-id /usr/lib/notification-daemon-1.0/notification-daemon -r'
|
||||
elif [[ -x "/usr/libexec/notification-daemon" ]]; then
|
||||
echo 'exec_always --no-startup-id /usr/libexec/notification-daemon -r'
|
||||
fi
|
||||
else
|
||||
# i3: use X11 notification daemons
|
||||
if [[ -x "/usr/lib/xfce4/notifyd/xfce4-notifyd" ]]; then
|
||||
echo 'exec_always --no-startup-id /usr/lib/xfce4/notifyd/xfce4-notifyd'
|
||||
elif [[ -x "/usr/lib/notification-daemon-1.0/notification-daemon" ]]; then
|
||||
echo 'exec_always --no-startup-id /usr/lib/notification-daemon-1.0/notification-daemon -r'
|
||||
elif [[ -x "/usr/libexec/notification-daemon" ]]; then
|
||||
# Work around for weird Void Linux stuff
|
||||
echo 'exec_always --no-startup-id /usr/libexec/notification-daemon -r'
|
||||
fi
|
||||
if [[ -x "/usr/lib/xfce4/notifyd/xfce4-notifyd" ]]; then
|
||||
echo 'exec_always --no-startup-id /usr/lib/xfce4/notifyd/xfce4-notifyd'
|
||||
elif [[ -x "/usr/lib/notification-daemon-1.0/notification-daemon" ]]; then
|
||||
echo 'exec_always --no-startup-id /usr/lib/notification-daemon-1.0/notification-daemon -r'
|
||||
elif [[ -x "/usr/libexec/notification-daemon" ]]; then
|
||||
# Work around for weird Void Linux stuff
|
||||
echo 'exec_always --no-startup-id /usr/libexec/notification-daemon -r'
|
||||
fi
|
||||
if command -v remind &> /dev/null && command -v notify-send &> /dev/null ; then
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/launch_remind.sh"
|
||||
@@ -1291,39 +1245,25 @@ fi
|
||||
if [[ $batteryAlert -eq 0 ]]; then
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/battery_alert.sh"
|
||||
fi
|
||||
if [[ $usingSway -ne 0 ]] && [[ -n "$screenlockPinHash" ]] && [[ "${screenlockAutolockSeconds:-0}" -gt 0 ]] && command -v xprintidle &> /dev/null; then
|
||||
if [[ -n "$screenlockPinHash" ]] && [[ "${screenlockAutolockSeconds:-0}" -gt 0 ]] && command -v xprintidle &> /dev/null; then
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/screenlock_autolock.sh ${screenlockAutolockSeconds}"
|
||||
fi
|
||||
# WayTray system tray daemon
|
||||
if command -v waytray-daemon &> /dev/null ; then
|
||||
echo 'exec_always --no-startup-id bash -c "pgrep -x waytray-daemon > /dev/null || waytray-daemon"'
|
||||
fi
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/i38-clipboard.py --daemon"
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/desktop.sh"
|
||||
if [[ $dex -eq 0 ]]; then
|
||||
echo '# Start XDG autostart .desktop files using dex. See also'
|
||||
echo '# https://wiki.archlinux.org/index.php/XDG_Autostart'
|
||||
if [[ $usingSway -eq 0 ]]; then
|
||||
echo 'exec --no-startup-id dex --autostart --environment sway'
|
||||
else
|
||||
echo 'exec --no-startup-id dex --autostart --environment i3'
|
||||
fi
|
||||
echo 'exec --no-startup-id dex --autostart --environment i3'
|
||||
else
|
||||
echo '# Startup applications'
|
||||
# x11bell is X11-only, skip on Sway/Wayland
|
||||
if command -v x11bell &> /dev/null && [[ $usingSway -ne 0 ]]; then
|
||||
if command -v x11bell &> /dev/null; then
|
||||
echo 'exec --no-startup-id x11bell play -nqV0 synth .1 sq norm -12'
|
||||
fi
|
||||
# Clipboard manager
|
||||
if [[ $usingSway -eq 0 ]]; then
|
||||
# Sway: use Wayland clipboard manager
|
||||
if command -v wl-paste &> /dev/null && command -v clipman &> /dev/null; then
|
||||
echo 'exec wl-paste -t text --watch clipman store'
|
||||
fi
|
||||
else
|
||||
# i3: use I38's accessible clipboard history daemon
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/i38-clipboard.py --daemon"
|
||||
fi
|
||||
echo "exec $screenReader"
|
||||
echo "exec_always --no-startup-id ${i3Path}/scripts/desktop.sh"
|
||||
fi)
|
||||
|
||||
# First run help documentation
|
||||
|
||||
+5
-13
@@ -54,8 +54,7 @@ class SystemCommands:
|
||||
}
|
||||
|
||||
optional_commands = {
|
||||
'xclip': 'Required for clipboard on X11',
|
||||
'wl-paste': 'Required for clipboard on Wayland',
|
||||
'xclip': 'Required for clipboard',
|
||||
'tesseract': 'Required for OCR functionality',
|
||||
}
|
||||
|
||||
@@ -1607,18 +1606,11 @@ class AiAssistant(Gtk.Window):
|
||||
def analyze_selected_in_thread():
|
||||
try:
|
||||
# First, try to get clipboard content (selected text)
|
||||
# Use wl-paste on Wayland, xclip on X11
|
||||
selected_text = ""
|
||||
if os.environ.get('WAYLAND_DISPLAY'):
|
||||
if SystemCommands.is_command_available('wl-paste'):
|
||||
clipboard_result = subprocess.run(['wl-paste', '-p'],
|
||||
capture_output=True, text=True, timeout=5)
|
||||
selected_text = clipboard_result.stdout.strip() if clipboard_result.returncode == 0 else ""
|
||||
else:
|
||||
if SystemCommands.is_command_available('xclip'):
|
||||
clipboard_result = subprocess.run(['xclip', '-o', '-selection', 'primary'],
|
||||
capture_output=True, text=True, timeout=5)
|
||||
selected_text = clipboard_result.stdout.strip() if clipboard_result.returncode == 0 else ""
|
||||
if SystemCommands.is_command_available('xclip'):
|
||||
clipboard_result = subprocess.run(['xclip', '-o', '-selection', 'primary'],
|
||||
capture_output=True, text=True, timeout=5)
|
||||
selected_text = clipboard_result.stdout.strip() if clipboard_result.returncode == 0 else ""
|
||||
|
||||
if selected_text:
|
||||
# We have selected text, analyze it
|
||||
|
||||
@@ -11,18 +11,11 @@
|
||||
# You should have received a copy of the GNU General Public License along with I38. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
path="$(readlink -f $0)"
|
||||
path="$(readlink -f "$0")"
|
||||
path="${path%/*/*}"
|
||||
path="${path##*/}"
|
||||
if [[ "$path" == "i3" ]]; then
|
||||
workSpace="$(i3-msg -t get_workspaces \
|
||||
| jq '.[] | select(.focused==true).name' \
|
||||
| cut -d"\"" -f2)"
|
||||
else
|
||||
workSpace="$(swaymsg -t get_workspaces \
|
||||
| jq '.[] | select(.focused==true).name' \
|
||||
| cut -d"\"" -f2)"
|
||||
fi
|
||||
workSpace="$(i3-msg -t get_workspaces \
|
||||
| jq '.[] | select(.focused==true).name' \
|
||||
| cut -d"\"" -f2)"
|
||||
left=9
|
||||
right=0
|
||||
msg="Workspace ${workSpace}"
|
||||
@@ -41,9 +34,9 @@ else
|
||||
right=9
|
||||
elif [[ ${workSpace} -gt 5 ]]; then
|
||||
right=9
|
||||
((left-=${workSpace}))
|
||||
((left-=workSpace))
|
||||
else
|
||||
((right+=${workSpace}))
|
||||
((right+=workSpace))
|
||||
fi
|
||||
fi
|
||||
play -nqV0 synth pi fade 0 .25 .15 pad 0 1 reverb overdrive riaa norm -8 speed 1 remix v0.${left} v0.${right} &
|
||||
|
||||
@@ -10,53 +10,25 @@
|
||||
|
||||
# You should have received a copy of the GNU General Public License along with I38. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# Find out if we're using i3 or sway
|
||||
if ! [[ -n "${WAYLAND_DISPLAY}" ]]; then
|
||||
cmd="i3-msg"
|
||||
scratchConfig="${XDG_CONFIG_HOME:-$HOME/.config}/i3"
|
||||
usingWayland=false
|
||||
else
|
||||
cmd="swaymsg"
|
||||
scratchConfig="${XDG_CONFIG_HOME:-$HOME/.config}/sway"
|
||||
usingWayland=true
|
||||
fi
|
||||
scratchConfig="${XDG_CONFIG_HOME:-$HOME/.config}/i3"
|
||||
scratchConfig+="/scratchpad"
|
||||
touch "${scratchConfig}"
|
||||
|
||||
# Get the class name of the focused window
|
||||
if [[ "$usingWayland" == "true" ]]; then
|
||||
# Wayland/Sway: use swaymsg to get focused window info
|
||||
class=$($cmd -t get_tree | jq -r '.. | select(.focused? == true) | .app_id // .window_properties.class' | head -n 1)
|
||||
else
|
||||
# X11/i3: use xdotool and xprop
|
||||
if ! command -v xdotool &> /dev/null || ! command -v xprop &> /dev/null; then
|
||||
notify-send "Error: xdotool and xprop required for i3"
|
||||
exit 1
|
||||
fi
|
||||
windowId=$(xdotool getactivewindow)
|
||||
class=$(xprop -id "$windowId" WM_CLASS | awk -F '"' '{print $4}')
|
||||
if ! command -v xdotool &> /dev/null || ! command -v xprop &> /dev/null; then
|
||||
notify-send "Error: xdotool and xprop required for i3"
|
||||
exit 1
|
||||
fi
|
||||
windowId=$(xdotool getactivewindow)
|
||||
class=$(xprop -id "$windowId" WM_CLASS | awk -F '"' '{print $4}')
|
||||
|
||||
if [[ -z "$class" ]]; then
|
||||
notify-send "Unable to move to scratchpad."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if it's already in the config
|
||||
if [[ "$usingWayland" == "true" ]]; then
|
||||
# Sway uses app_id for Wayland-native apps, class for XWayland apps
|
||||
if ! grep -q "app_id=\"$class\"" "$scratchConfig" && ! grep -q "class=\"$class\"" "$scratchConfig"; then
|
||||
echo "for_window [app_id=\"$class\"] move to scratchpad" >> "$scratchConfig"
|
||||
notify-send "Added window app_id $class to scratchpad"
|
||||
fi
|
||||
# Move the window to scratchpad now (try both app_id and class)
|
||||
$cmd "[app_id=\"$class\"] move to scratchpad" 2>/dev/null || $cmd "[class=\"$class\"] move to scratchpad"
|
||||
else
|
||||
# i3 uses class
|
||||
if ! grep -q "class=\"$class\"" "$scratchConfig"; then
|
||||
echo "for_window [class=\"$class\"] move to scratchpad" >> "$scratchConfig"
|
||||
notify-send "Added window class $class to scratchpad"
|
||||
fi
|
||||
# Move the window to scratchpad now
|
||||
$cmd "[class=\"$class\"] move to scratchpad"
|
||||
if ! grep -q "class=\"$class\"" "$scratchConfig"; then
|
||||
echo "for_window [class=\"$class\"] move to scratchpad" >> "$scratchConfig"
|
||||
notify-send "Added window class $class to scratchpad"
|
||||
fi
|
||||
i3-msg "[class=\"$class\"] move to scratchpad"
|
||||
|
||||
+4
-36
@@ -20,29 +20,8 @@ trim_whitespace() {
|
||||
|
||||
get_shortcuts_file() {
|
||||
local configHome="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
local candidatePath=
|
||||
local candidatePath="${configHome}/i3/desktop_shortcuts"
|
||||
|
||||
if [[ -n "${SWAYSOCK:-}" ]]; then
|
||||
candidatePath="${configHome}/sway/desktop_shortcuts"
|
||||
if [[ -r "$candidatePath" ]]; then
|
||||
printf '%s\n' "$candidatePath"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
candidatePath="${configHome}/i3/desktop_shortcuts"
|
||||
if [[ -r "$candidatePath" ]]; then
|
||||
printf '%s\n' "$candidatePath"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
candidatePath="${configHome}/i3/desktop_shortcuts"
|
||||
if [[ -r "$candidatePath" ]]; then
|
||||
printf '%s\n' "$candidatePath"
|
||||
return 0
|
||||
fi
|
||||
|
||||
candidatePath="${configHome}/sway/desktop_shortcuts"
|
||||
if [[ -r "$candidatePath" ]]; then
|
||||
printf '%s\n' "$candidatePath"
|
||||
return 0
|
||||
@@ -54,7 +33,6 @@ get_shortcuts_file() {
|
||||
build_launch_command() {
|
||||
local shortcutCommand="$1"
|
||||
local shortcutWorkspace="$2"
|
||||
local wmCommand=
|
||||
local workspaceEscaped=
|
||||
|
||||
if [[ -z "$shortcutWorkspace" ]]; then
|
||||
@@ -62,28 +40,18 @@ build_launch_command() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "${SWAYSOCK:-}" ]] && command -v swaymsg &> /dev/null; then
|
||||
wmCommand="swaymsg"
|
||||
elif [[ -n "${I3SOCK:-}" ]] && command -v i3-msg &> /dev/null; then
|
||||
wmCommand="i3-msg"
|
||||
elif [[ -n "${WAYLAND_DISPLAY:-}" ]] && command -v swaymsg &> /dev/null; then
|
||||
wmCommand="swaymsg"
|
||||
elif command -v i3-msg &> /dev/null; then
|
||||
wmCommand="i3-msg"
|
||||
fi
|
||||
|
||||
if [[ -z "$wmCommand" ]]; then
|
||||
if ! command -v i3-msg &> /dev/null; then
|
||||
printf '%s\n' "$shortcutCommand"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$shortcutWorkspace" =~ ^[0-9]+$ ]]; then
|
||||
printf '%s workspace number %s && %s\n' "$wmCommand" "$shortcutWorkspace" "$shortcutCommand"
|
||||
printf 'i3-msg workspace number %s && %s\n' "$shortcutWorkspace" "$shortcutCommand"
|
||||
return 0
|
||||
fi
|
||||
|
||||
workspaceEscaped=$(printf '%q' "$shortcutWorkspace")
|
||||
printf '%s workspace %s && %s\n' "$wmCommand" "$workspaceEscaped" "$shortcutCommand"
|
||||
printf 'i3-msg workspace %s && %s\n' "$workspaceEscaped" "$shortcutCommand"
|
||||
}
|
||||
|
||||
desktopPath="${HOME}/Desktop"
|
||||
|
||||
+13
-44
@@ -19,58 +19,27 @@
|
||||
|
||||
set -e
|
||||
|
||||
# Detect if we're on Wayland or X11
|
||||
if [[ -n "${WAYLAND_DISPLAY}" ]]; then
|
||||
usingWayland=true
|
||||
else
|
||||
usingWayland=false
|
||||
fi
|
||||
|
||||
get_kbdlayout() {
|
||||
if [[ "$usingWayland" == "true" ]]; then
|
||||
# Sway: Get keyboard layout from input devices
|
||||
# This gets the xkb_active_layout_name from the first keyboard
|
||||
layout=$(swaymsg -t get_inputs | jq -r '.[] | select(.type=="keyboard") | .xkb_active_layout_name' | head -n 1)
|
||||
echo "$layout"
|
||||
else
|
||||
# i3: Use setxkbmap
|
||||
layout=$(setxkbmap -query | grep -oP 'layout:\s*\K([\w,]+)')
|
||||
variant=$(setxkbmap -query | grep -oP 'variant:\s*\K(\w+)')
|
||||
echo "$layout" "$variant"
|
||||
fi
|
||||
layout=$(setxkbmap -query | grep -oP 'layout:\s*\K([\w,]+)')
|
||||
variant=$(setxkbmap -query | grep -oP 'variant:\s*\K(\w+)')
|
||||
echo "$layout" "$variant"
|
||||
}
|
||||
|
||||
set_kbdlayout() {
|
||||
eval "array=($1)"
|
||||
read -r -a array <<< "$1"
|
||||
|
||||
if [[ "$usingWayland" == "true" ]]; then
|
||||
# Sway: Switch to next keyboard layout
|
||||
# Sway cycles through layouts configured in the config, so we just trigger next
|
||||
swaymsg input type:keyboard xkb_switch_layout next &&
|
||||
spd-say -P important -Cw "${array[@]}"
|
||||
else
|
||||
# i3: Use setxkbmap
|
||||
setxkbmap "${array[@]}" &&
|
||||
spd-say -P important -Cw "${array[@]}"
|
||||
fi
|
||||
setxkbmap "${array[@]}" &&
|
||||
spd-say -P important -Cw "${array[@]}"
|
||||
}
|
||||
|
||||
cycle() {
|
||||
if [[ "$usingWayland" == "true" ]]; then
|
||||
# Sway: Just switch to next layout (Sway handles cycling internally)
|
||||
swaymsg input type:keyboard xkb_switch_layout next
|
||||
currentLayout=$(get_kbdlayout)
|
||||
spd-say -P important -Cw "$currentLayout"
|
||||
else
|
||||
# i3: Cycle through provided layouts
|
||||
currentLayout=$(get_kbdlayout | xargs)
|
||||
layouts=("$@" "$1") # add the first one at the end so that it cycles
|
||||
index=0
|
||||
while [ "${layouts[$index]}" != "$currentLayout" ] && [ $index -lt "${#layouts[@]}" ]; do index=$((index + 1)); done
|
||||
nextIndex=$((index + 1))
|
||||
nextLayout=${layouts[$nextIndex]}
|
||||
set_kbdlayout "$nextLayout"
|
||||
fi
|
||||
currentLayout=$(get_kbdlayout | xargs)
|
||||
layouts=("$@" "$1") # add the first one at the end so that it cycles
|
||||
index=0
|
||||
while [ "${layouts[$index]}" != "$currentLayout" ] && [ $index -lt "${#layouts[@]}" ]; do index=$((index + 1)); done
|
||||
nextIndex=$((index + 1))
|
||||
nextLayout=${layouts[$nextIndex]}
|
||||
set_kbdlayout "$nextLayout"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -65,18 +65,6 @@ case "$powerAction" in
|
||||
esac
|
||||
|
||||
try_logout() {
|
||||
if [[ -n "${SWAYSOCK:-}" ]] && command -v swaymsg &> /dev/null; then
|
||||
swaymsg -t command exit &> /dev/null
|
||||
return $?
|
||||
fi
|
||||
if [[ -n "${I3SOCK:-}" ]] && command -v i3-msg &> /dev/null; then
|
||||
i3-msg -t command exit &> /dev/null
|
||||
return $?
|
||||
fi
|
||||
if command -v swaymsg &> /dev/null; then
|
||||
swaymsg -t command exit &> /dev/null
|
||||
return $?
|
||||
fi
|
||||
if command -v i3-msg &> /dev/null; then
|
||||
i3-msg -t command exit &> /dev/null
|
||||
return $?
|
||||
|
||||
+18
-20
@@ -42,7 +42,7 @@ add_reminder() {
|
||||
done
|
||||
info="${info#|#}"
|
||||
# Get information for reminder into an array
|
||||
IFS='|' read -a reminder <<< $info
|
||||
IFS='|' read -r -a reminder <<< "$info"
|
||||
# Fix time to be 2 digits.
|
||||
[[ ${#reminder[3]} -eq 1 ]] && reminder[3]="0${reminder[3]}"
|
||||
[[ ${#reminder[4]} -eq 1 ]] && reminder[4]="0${reminder[4]}"
|
||||
@@ -83,7 +83,7 @@ add_custom_reminder() {
|
||||
done
|
||||
info="${info#|#}"
|
||||
# Get information for reminder into an array
|
||||
IFS='|' read -a reminder <<< $info
|
||||
IFS='|' read -r -a reminder <<< "$info"
|
||||
if [[ "${reminder[0]}" != "# " ]]; then
|
||||
echo "# ${reminder[0]}" >> ~/.reminders
|
||||
fi
|
||||
@@ -112,7 +112,7 @@ add_daily_reminder() {
|
||||
fi
|
||||
|
||||
# Get information for reminder into an array
|
||||
IFS='|' read -a reminder <<< $info
|
||||
IFS='|' read -r -a reminder <<< "$info"
|
||||
|
||||
# Fix time to be 2 digits.
|
||||
[[ ${#reminder[1]} -eq 1 ]] && reminder[1]="0${reminder[1]}"
|
||||
@@ -153,7 +153,7 @@ add_monthly_reminder() {
|
||||
fi
|
||||
|
||||
# Get information for reminder into an array
|
||||
IFS='|' read -a reminder <<< $info
|
||||
IFS='|' read -r -a reminder <<< "$info"
|
||||
|
||||
# Fix time and date to be 2 digits.
|
||||
[[ ${#reminder[2]} -eq 1 ]] && reminder[2]="0${reminder[2]}"
|
||||
@@ -205,7 +205,7 @@ add_weekly_reminder() {
|
||||
fi
|
||||
|
||||
# Get information for reminder into an array
|
||||
IFS='|' read -a reminder <<< $info
|
||||
IFS='|' read -r -a reminder <<< "$info"
|
||||
|
||||
# Fix time to be 2 digits.
|
||||
[[ ${#reminder[9]} -eq 1 ]] && reminder[9]="0${reminder[9]}"
|
||||
@@ -272,27 +272,28 @@ view_reminders() {
|
||||
done
|
||||
|
||||
# Display the reminders
|
||||
reminder="$(yad --list --title "I38 - Reminders" --text "Current reminders:" \
|
||||
selectedReminder="$(yad --list --title "I38 - Reminders" --text "Current reminders:" \
|
||||
--column "Reminder" "${yadMenu[@]}" \
|
||||
--button="Close!gtk-ok:1" --button="Delete!gtk-delete:0" --response=1)"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
yadResult=$?
|
||||
if [[ $yadResult -ne 0 ]]; then
|
||||
return
|
||||
fi
|
||||
if [[ "${reminder:0:1}" == "#" ]]; then
|
||||
if [[ "${selectedReminder:0:1}" == "#" ]]; then
|
||||
error "Please select the actual reminder to be deleted, anything starting with # is only a comment. Nothing changed."
|
||||
return
|
||||
fi
|
||||
# Remove the | from the end of reminder
|
||||
reminder="${reminder%|}"
|
||||
selectedReminder="${selectedReminder%|}"
|
||||
# Find the index to remove from lines.
|
||||
for i in "${!yadMenu[@]}" ; do
|
||||
if [[ "${yadMenu[i]}" == "${reminder}" ]]; then
|
||||
if [[ "${yadMenu[i]}" == "${selectedReminder}" ]]; then
|
||||
# Delete selected reminder and possible preceeding comment.
|
||||
commentIndex=$((i - 1))
|
||||
if [[ "${lines[commentIndex]:0:1}" == "#" ]]; then
|
||||
unset lines[$commentIndex]
|
||||
unset "lines[$commentIndex]"
|
||||
fi
|
||||
unset lines[$i]
|
||||
unset "lines[$i]"
|
||||
message "Reminder deleted."
|
||||
printf "%s\n" "${lines[@]}" > ~/.reminders
|
||||
fi
|
||||
@@ -330,11 +331,7 @@ if [[ $# -ne 0 ]]; then
|
||||
url="${url%[[:space:].?!]}"
|
||||
fi
|
||||
if [[ "${#url}" -gt 3 ]]; then
|
||||
# Copy URL to clipboard using appropriate tool
|
||||
if [[ -n "${WAYLAND_DISPLAY}" ]] && command -v wl-copy &> /dev/null; then
|
||||
echo "${url}" | wl-copy
|
||||
notify-send --hint=int:transient:1 -t 500 -r 38 "${notification} The URL has been copied to the clipboard."
|
||||
elif command -v xclip &> /dev/null; then
|
||||
if command -v xclip &> /dev/null; then
|
||||
echo "${url}" | xclip -selection clipboard
|
||||
notify-send --hint=int:transient:1 -t 500 -r 38 "${notification} The URL has been copied to the clipboard."
|
||||
else
|
||||
@@ -347,7 +344,7 @@ if [[ $# -ne 0 ]]; then
|
||||
fi
|
||||
|
||||
while : ; do
|
||||
action=$(yad --title "I38 - Reminders" --form \
|
||||
yad --title "I38 - Reminders" --form \
|
||||
--button="_View Today's Reminders!gtk-info":3 \
|
||||
--button="_View All Reminders!gtk-info":4 \
|
||||
--button="_Add Reminder!gtk-edit":0 \
|
||||
@@ -356,9 +353,10 @@ while : ; do
|
||||
--button="Add Monthly Reminder!gtk-edit":6 \
|
||||
--button="Add Custom Reminder!gtk-edit":7 \
|
||||
--button="Close!gtk-cancel":1 \
|
||||
--separator="")
|
||||
--separator=""
|
||||
yadResult=$?
|
||||
|
||||
case $? in
|
||||
case $yadResult in
|
||||
0)
|
||||
# Single reminder
|
||||
add_reminder
|
||||
|
||||
@@ -10,24 +10,12 @@
|
||||
|
||||
# You should have received a copy of the GNU General Public License along with I38. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# Not for multiple screens.
|
||||
# Detect if we're on Wayland or X11
|
||||
if [[ -n "${WAYLAND_DISPLAY}" ]]; then
|
||||
# Sway/Wayland: Get the name of the first output
|
||||
screenName="$(swaymsg -t get_outputs | jq -r '.[0].name')"
|
||||
if [[ -z "$screenName" ]]; then
|
||||
notify-send "Error: Could not detect output"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# i3/X11: Get the name of the screen
|
||||
if ! command -v xrandr &> /dev/null; then
|
||||
notify-send "Error: xrandr not found"
|
||||
exit 1
|
||||
fi
|
||||
screenName="$(xrandr --query | grep "connected" | cut -d ' ' -f1 | head -n 1)"
|
||||
if ! command -v xrandr &> /dev/null; then
|
||||
notify-send "Error: xrandr not found"
|
||||
exit 1
|
||||
fi
|
||||
screenName="$(xrandr --query | grep "connected" | cut -d ' ' -f1 | head -n 1)"
|
||||
|
||||
menuOptions=(
|
||||
"1.0" "Maximum Brightness"
|
||||
@@ -43,28 +31,7 @@ if [[ ${#brightness} -lt 1 ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Apply brightness setting
|
||||
if [[ -n "${WAYLAND_DISPLAY}" ]]; then
|
||||
# Sway: Use swaymsg to set output brightness
|
||||
# Note: Sway doesn't have native brightness control, using wlr-randr if available
|
||||
if command -v wlr-randr &> /dev/null; then
|
||||
wlr-randr --output "${screenName}" --brightness "${brightness%%|*}" &&
|
||||
spd-say -P important -Cw "Screen set to ${brightness#*|}."
|
||||
else
|
||||
# Fallback to gamma adjustment via wl-gammactl or brightnessctl
|
||||
if command -v brightnessctl &> /dev/null; then
|
||||
brightnessValue=$(echo "${brightness%%|*} * 100" | bc)
|
||||
brightnessctl set "${brightnessValue%.*}%" &&
|
||||
spd-say -P important -Cw "Screen set to ${brightness#*|}."
|
||||
else
|
||||
notify-send "Error: wlr-randr or brightnessctl required for Sway brightness control"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# i3: Use xrandr
|
||||
xrandr --output "${screenName}" --brightness "${brightness%%|*}" &&
|
||||
spd-say -P important -Cw "Screen set to ${brightness#*|}."
|
||||
fi
|
||||
xrandr --output "${screenName}" --brightness "${brightness%%|*}" &&
|
||||
spd-say -P important -Cw "Screen set to ${brightness#*|}."
|
||||
|
||||
exit 0
|
||||
|
||||
+8
-17
@@ -39,28 +39,19 @@ if ! command -v sha512sum &> /dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wmMsg="i3-msg"
|
||||
if [[ -n "${SWAYSOCK:-}" ]] && command -v swaymsg &> /dev/null; then
|
||||
wmMsg="swaymsg"
|
||||
elif [[ -n "${I3SOCK:-}" ]] && command -v i3-msg &> /dev/null; then
|
||||
wmMsg="i3-msg"
|
||||
elif command -v swaymsg &> /dev/null; then
|
||||
wmMsg="swaymsg"
|
||||
elif command -v i3-msg &> /dev/null; then
|
||||
wmMsg="i3-msg"
|
||||
else
|
||||
yad --title "I38" --text "No i3 or sway command interface was found for screen lock." --button "Close:0"
|
||||
if ! command -v i3-msg &> /dev/null; then
|
||||
yad --title "I38" --text "No i3 command interface was found for screen lock." --button "Close:0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
currentWorkspace="$($wmMsg -t get_workspaces | jq -r '.[] | select(.focused==true) | .name')"
|
||||
currentWorkspace="$(i3-msg -t get_workspaces | jq -r '.[] | select(.focused==true) | .name')"
|
||||
lockWorkspace="i38-lock"
|
||||
if $wmMsg -t get_workspaces | jq -e --arg name "$lockWorkspace" '.[] | select(.name==$name)' &> /dev/null; then
|
||||
if i3-msg -t get_workspaces | jq -e --arg name "$lockWorkspace" '.[] | select(.name==$name)' &> /dev/null; then
|
||||
lockWorkspace="i38-lock-$$"
|
||||
fi
|
||||
|
||||
$wmMsg -t command "workspace --no-auto-back-and-forth \"$lockWorkspace\"" &> /dev/null
|
||||
$wmMsg -t command "mode screenlock" &> /dev/null
|
||||
i3-msg -t command "workspace --no-auto-back-and-forth \"$lockWorkspace\"" &> /dev/null
|
||||
i3-msg -t command "mode screenlock" &> /dev/null
|
||||
|
||||
attemptCount=0
|
||||
while : ; do
|
||||
@@ -92,9 +83,9 @@ while : ; do
|
||||
attemptCount=$((attemptCount + 1))
|
||||
done
|
||||
|
||||
$wmMsg -t command "mode default" &> /dev/null
|
||||
i3-msg -t command "mode default" &> /dev/null
|
||||
if [[ -n "$currentWorkspace" ]]; then
|
||||
$wmMsg -t command "workspace \"$currentWorkspace\"" &> /dev/null
|
||||
i3-msg -t command "workspace \"$currentWorkspace\"" &> /dev/null
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
+1
-29
@@ -11,10 +11,6 @@
|
||||
# You should have received a copy of the GNU General Public License along with I38. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
path="$(readlink -f $0)"
|
||||
path="${path%/*/*}"
|
||||
path="${path##*/}"
|
||||
if [[ "$path" == "i3" ]]; then
|
||||
mapfile -t windowList < <(python3 -c '
|
||||
import i3ipc
|
||||
|
||||
@@ -28,28 +24,4 @@ id="$(yad --title "I38" --list --separator "" --column "id" --column "Select Win
|
||||
if [[ -z "${id}" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
i3-msg \[id="${id}"\] focus
|
||||
else
|
||||
mapfile -t windowList < <(python3 -c '
|
||||
import i3ipc
|
||||
|
||||
i3 = i3ipc.Connection()
|
||||
|
||||
for con in i3.get_tree():
|
||||
if con.window or con.type == "con":
|
||||
if con.name:
|
||||
print(con.window)
|
||||
print(con.name)')
|
||||
|
||||
# Remove the first entry if it is "none"
|
||||
if [[ "${windowList[0]}" == "none" ]]; then
|
||||
unset "windowList[0]"
|
||||
fi
|
||||
|
||||
id="$(yad --title "I38" --list --separator "" --column "id" --column "Select Window" --hide-column 1 --print-column 1 "${windowList[@]}")"
|
||||
|
||||
if [[ -z "${id}" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
swaymsg \[id="${id}"\] focus
|
||||
fi
|
||||
i3-msg \[id="${id}"\] focus
|
||||
|
||||
Reference in New Issue
Block a user