Compare commits

...

7 Commits

19 changed files with 461 additions and 384 deletions
+3
View File
@@ -3,3 +3,6 @@ config/fish/functions
config/fish/fish_variables config/fish/fish_variables
config/nvim/nvim-pack-lock.json config/nvim/nvim-pack-lock.json
config/alacritty/dank-theme.toml config/alacritty/dank-theme.toml
scripts/bin/Obsidian
scripts/bin/ols
+65
View File
@@ -0,0 +1,65 @@
#################################
# Fading #
#################################
fading = true;
fade-in-step = 0.08;
fade-out-step = 0.08;
#################################
# Transparency / Opacity #
#################################
frame-opacity = 1.0;
#################################
# Corners #
#################################
corner-radius = 13;
#################################
# FAST SNAPPY ANIMATIONS #
#################################
animations = (
{
triggers = ["open", "show"];
preset = "appear";
duration = 0.20;
},
{
triggers = ["close", "hide"];
preset = "disappear";
duration = 0.20;
},
{
triggers = ["geometry"];
preset = "geometry-change";
duration = 0.30;
}
);
#################################
# General Settings #
#################################
backend = "xrender";
dithered-present = false;
vsync = true;
detect-rounded-corners = true;
detect-client-opacity = true;
detect-transient = true;
use-damage = true;
log-level = "warn";
#################################
# Window Rules #
#################################
rules: (
# No rounded corners on dock and desktop
{
match = "window_type = 'dock' || window_type = 'desktop' || class_g = 'Rofi'";
corner-radius = 0;
},
# Dim all app windows besides systems stuff
{
match = "focused = 0 && window_type = 'normal' && class_g != 'Rofi'";
dim = 0.45;
}
)
+2 -3
View File
@@ -4,11 +4,11 @@
;========================================================== ;==========================================================
[colors] [colors]
background = #282A33 background = #212121
background-alt = #3c3c3c background-alt = #3c3c3c
foreground = #d3dae3 foreground = #d3dae3
foreground-alt = #000000 foreground-alt = #000000
accent = #5294e2 accent = #616161
accent-alt = #6ba0e8 accent-alt = #6ba0e8
red = #e35b5b red = #e35b5b
green = #98c379 green = #98c379
@@ -130,4 +130,3 @@ tray-background = ${colors.background}
[settings] [settings]
screenchange-reload = true screenchange-reload = true
pseudo-transparency = false pseudo-transparency = false
+7 -7
View File
@@ -26,7 +26,7 @@ configuration {
window { window {
width: 700px; width: 700px;
background-color: #282A33; background-color: #212121;
border: 0; border: 0;
padding: 0; padding: 0;
children: [ vertbox ]; children: [ vertbox ];
@@ -58,13 +58,13 @@ button selected.normal {
error-message { error-message {
border: 0; border: 0;
background-color: #282A33; background-color: #212121;
padding: 10px 25px; padding: 10px 25px;
} }
inputbar { inputbar {
font: "Inter 15"; font: "Inter 15";
background-color: #282A33; background-color: #212121;
border-color: #1c1c1c; border-color: #1c1c1c;
border: 0 0 1px solid 0; border: 0 0 1px solid 0;
padding: 10px 15px; padding: 10px 15px;
@@ -98,7 +98,7 @@ listview {
border: 0 0 1px 0; border: 0 0 1px 0;
border-color: #1c1c1c; border-color: #1c1c1c;
padding: 0; padding: 0;
background-color: #282A33; background-color: #212121;
children: [element-icon, element-text]; children: [element-icon, element-text];
} }
@@ -112,7 +112,7 @@ toolbar {
children: [ mode-switcher ]; children: [ mode-switcher ];
expand: false; expand: false;
padding: 0 5px 3px 0; padding: 0 5px 3px 0;
background-color: #282A33; background-color: #212121;
} }
element { element {
@@ -126,14 +126,14 @@ element.normal.active,
element.alternate.normal, element.alternate.normal,
element.alternate.urgent, element.alternate.urgent,
element.alternate.active { element.alternate.active {
background-color: #282A33; background-color: #212121;
text-color: #d3dae3; text-color: #d3dae3;
} }
element.selected.normal, element.selected.normal,
element.selected.urgent, element.selected.urgent,
element.selected.active { element.selected.active {
background-color: #282A33; background-color: #424242;
text-color: #d3dae3; text-color: #d3dae3;
} }
-168
View File
@@ -1,168 +0,0 @@
[
// ─── UNBINDS ────────────────────────────────────────────────────────────────
{
"context": "Editor && vim_mode == insert",
"bindings": { "ctrl-l": null, "ctrl-h": null },
},
{
"context": "FileFinder || FileFinder > Picker > Editor || FileFinder > Picker > menu",
"bindings": { "ctrl-l": null, "ctrl-h": null },
},
{
"context": "BufferSearchBar",
"bindings": { "ctrl-l": null, "ctrl-h": null },
},
{
"context": "vim_mode == literal",
"bindings": { "ctrl-l": null, "ctrl-h": null },
},
{
"context": "VimControl && !menu",
"bindings": { "ctrl-b": null, "ctrl-o": null, "ctrl-h": null, "ctrl-j": null, "ctrl-k": null, "ctrl-l": null },
},
{
"context": "Workspace",
"bindings": { "ctrl-b": null, "ctrl-h": null, "ctrl-j": null, "ctrl-k": null, "ctrl-l": null },
},
{
"context": "Editor",
"bindings": { "ctrl-h": null, "ctrl-j": null, "ctrl-k": null, "ctrl-l": null },
},
{
"unbind": { "ctrl-o": "workspace::OpenFiles" },
},
// ─── EDITOR ─────────────────────────────────────────────────────────────────
{
"context": "Editor",
"bindings": {
"ctrl-e": "project_panel::Toggle",
"ctrl-f": "pane::DeploySearch",
"ctrl-o": "terminal_panel::Toggle",
"ctrl-m": "tab_switcher::ToggleAll",
},
},
// ─── BUFFER SEARCH BAR ──────────────────────────────────────────────────────
{
"context": "BufferSearchBar",
"bindings": {
"ctrl-r": "search::ToggleReplace",
},
},
// ─── PROJECT SEARCH BAR ─────────────────────────────────────────────────────
{
"context": "ProjectSearchBar",
"bindings": {
"ctrl-r": "search::ToggleReplace",
},
},
// ─── PROJECT SEARCH RESULTS ──────────────────────────────────────────────────
{
"context": "VimControl && !menu",
"bindings": {
"enter": "editor::OpenExcerpts",
},
},
// ─── PROJECT PANEL (FILE TREE) ───────────────────────────────────────────────
{
"context": "ProjectPanel && not_editing",
"bindings": {
"ctrl-e": "project_panel::Toggle",
"a": "project_panel::NewFile",
"d": "project_panel::Delete",
"r": "project_panel::Rename",
},
},
// ─── TERMINAL ───────────────────────────────────────────────────────────────
{
"context": "Terminal",
"bindings": {
"ctrl-o": "terminal_panel::Toggle",
"ctrl-q": "pane::CloseActiveItem",
},
},
// ─── PANE NAVIGATION (vim-style) ────────────────────────────────────────────
{
"context": "VimControl && vim_mode == normal && !menu",
"bindings": {
"ctrl-h": "workspace::ActivatePaneLeft",
"ctrl-l": "workspace::ActivatePaneRight",
"ctrl-k": "workspace::ActivatePaneUp",
"ctrl-j": "workspace::ActivatePaneDown",
},
},
{
"context": "Pane && not_editing",
"bindings": {
"ctrl-h": "workspace::ActivatePaneLeft",
"ctrl-l": "workspace::ActivatePaneRight",
"ctrl-k": "workspace::ActivatePaneUp",
"ctrl-j": "workspace::ActivatePaneDown",
},
},
{
"context": "Terminal",
"bindings": {
"ctrl-h": "workspace::ActivatePaneLeft",
"ctrl-l": "workspace::ActivatePaneRight",
"ctrl-k": "workspace::ActivatePaneUp",
"ctrl-j": "workspace::ActivatePaneDown",
},
},
{
"context": "ProjectPanel",
"bindings": {
"ctrl-h": "workspace::ActivatePaneLeft",
"ctrl-l": "workspace::ActivatePaneRight",
"ctrl-k": "workspace::ActivatePaneUp",
"ctrl-j": "workspace::ActivatePaneDown",
},
},
// ─── WORKSPACE ──────────────────────────────────────────────────────────────
{
"context": "Workspace",
"bindings": {
"ctrl-e": "project_panel::Toggle",
"ctrl-o": "terminal_panel::Toggle",
"ctrl-p": "file_finder::Toggle",
},
},
// ─── CTRL-W CLOSE → CTRL-W Q ────────────────────────────────────────────────
{
"context": "Pane",
"bindings": { "ctrl-w": null },
},
{
"context": "Workspace",
"bindings": { "ctrl-w": null },
},
{
"context": "SettingsWindow",
"bindings": { "ctrl-w": null },
},
{
"context": "Pane",
"bindings": { "ctrl-w q": "pane::CloseActiveItem" },
},
{
"context": "SettingsWindow",
"bindings": { "ctrl-w q": "workspace::CloseWindow" },
},
{
"context": "Workspace",
"unbind": {
"ctrl-`": "terminal_panel::Toggle",
},
},
{
"context": "Workspace",
"bindings": {
"ctrl-`": "projects::OpenRecent",
},
},
{
"context": "Workspace",
"unbind": {
"ctrl-r": "projects::OpenRecent",
},
},
]
-161
View File
@@ -1,161 +0,0 @@
{
"use_system_window_tabs": false,
"window_decorations": "server",
// ─── CORE BEHAVIOR ───────────────────────────────────────────────────────────
"show_wrap_guides": false,
"which_key": { "enabled": true },
"cursor_shape": "block",
"vim_mode": true,
"base_keymap": "VSCode",
"restore_on_startup": "last_workspace",
"disable_ai": true,
"session": { "trust_all_worktrees": true },
"telemetry": { "diagnostics": false, "metrics": false },
// ─── EDITOR BEHAVIOR ─────────────────────────────────────────────────────────
"tab_size": 4,
"hard_tabs": true,
"soft_wrap": "editor_width",
"show_whitespaces": "none",
"format_on_save": "off",
"use_on_type_format": true,
"centered_layout": {
"left_padding": 0.15,
"right_padding": 0.15,
},
"indent_guides": {
"coloring": "fixed",
"line_width": 1,
"active_line_width": 2,
},
"gutter": {
"bookmarks": false,
"runnables": false,
},
// ─── FONTS & TEXT RENDERING ──────────────────────────────────────────────────
"buffer_font_family": "JetBrainsMono Nerd Font Mono",
"buffer_font_size": 15.7,
"buffer_font_features": { "liga": false },
"buffer_line_height": { "custom": 2.2 },
"ui_font_family": "Inter Display",
"ui_font_size": 16.5,
// ─── THEME & APPEARANCE ──────────────────────────────────────────────────────
"icon_theme": "Warm Charmed Icons",
"theme": "Kanagawa Wave - No Italics",
"theme_overrides": {
"VSCode Dark Modern": {
"border": "#1e1e1e",
"border.variant": "#303030",
"title_bar.background": "#1e1e1e",
"panel.background": "#1e1e1e",
"panel.focused_border": "#bbbbbb",
"editor.document_highlight.read_background": "#00000000",
"editor.document_highlight.write_background": "#00000000",
},
},
"scrollbar": { "selected_symbol": true, "show": "never" },
// ─── TAB BAR & TABS ──────────────────────────────────────────────────────────
"tab_bar": {
"show": false,
"show_nav_history_buttons": false,
"show_tab_bar_buttons": false,
},
"tabs": {
"close_position": "left",
"file_icons": false,
"git_status": false,
},
// ─── TOOLBAR & STATUS BAR ────────────────────────────────────────────────────
"toolbar": {
"breadcrumbs": false,
"quick_actions": false,
"selections_menu": false,
"agent_review": false,
},
"status_bar": {
"cursor_position_button": true,
"active_language_button": true,
},
"title_bar": {
"show_menus": false,
"button_layout": "platform_default",
"show_onboarding_banner": false,
"show_project_items": false,
"show_branch_status_icon": false,
"show_branch_name": false,
"show_user_picture": false,
"show_user_menu": false,
"show_sign_in": false,
},
// ─── PANELS & DOCKS ──────────────────────────────────────────────────────────
"project_panel": {
"dock": "left",
"starts_open": false,
"hide_root": true,
"bold_folder_labels": true,
"button": false,
},
"outline_panel": { "button": true, "dock": "left" },
"git_panel": { "dock": "left" },
"collaboration_panel": { "dock": "left" },
"terminal": {
"dock": "right",
"button": false,
},
"agent": {
"dock": "right",
"favorite_models": [],
"model_parameters": [],
},
// ─── BUTTONS ─────────────────────────────────────────────────────────────────
"search": { "button": true },
"debugger": { "button": false },
"diagnostics": { "button": false },
// ─── GIT INTEGRATION ───────────────────────────────────────────────────────
"git": {
"blame": {
"show_avatar": false
},
"inline_blame": {
"enabled": false
},
"git_gutter": "tracked_files",
"enable_diff": true,
"enable_status": true
},
// ─── LANGUAGE SERVERS ────────────────────────────────────────────────────────
"languages": {
"PHP": {
"language_servers": [
"intelephense",
"!phpactor",
"!phptools",
"!outsourced",
"tailwindcss-language-server",
"...",
],
},
"HTML": {
"language_servers": ["!tailwindcss-language-server", "..."],
},
"CSS": {
"language_servers": ["!tailwindcss-language-server", "..."],
},
"JavaScript": {
"language_servers": ["!tailwindcss-language-server", "..."],
},
"TypeScript": {
"language_servers": ["!tailwindcss-language-server", "..."],
},
"JSON": {
"language_servers": ["!json-language-server", "..."],
},
"Markdown": {
"language_servers": [
"markdown-oxide",
"!tailwindcss-language-server",
"!json-language-server",
"...",
],
},
},
}
+5 -6
View File
@@ -2,7 +2,6 @@
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------
## GLOBAL VARS ## GLOBAL VARS
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------
DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------
@@ -87,12 +86,12 @@ if [ "$DO_LINKS" = true ]; then
link_file "$DOTFILES_DIR/config/kanata" "$HOME/.config/kanata" link_file "$DOTFILES_DIR/config/kanata" "$HOME/.config/kanata"
link_file "$DOTFILES_DIR/config/fish" "$HOME/.config/fish" link_file "$DOTFILES_DIR/config/fish" "$HOME/.config/fish"
link_file "$DOTFILES_DIR/config/alacritty" "$HOME/.config/alacritty" link_file "$DOTFILES_DIR/config/alacritty" "$HOME/.config/alacritty"
link_file "$DOTFILES_DIR/config/nvim" "$HOME/.config/nvim"
link_file "$DOTFILES_DIR/config/zed/keymap.json" "$HOME/.config/zed/keymap.json"
link_file "$DOTFILES_DIR/config/zed/settings.json" "$HOME/.config/zed/settings.json"
link_file "$DOTFILES_DIR/config/lf" "$HOME/.config/lf" link_file "$DOTFILES_DIR/config/lf" "$HOME/.config/lf"
link_file "$DOTFILES_DIR/config/picom" "$HOME/.config/picom"
link_file "$DOTFILES_DIR/config/polybar" "$HOME/.config/polybar" link_file "$DOTFILES_DIR/config/polybar" "$HOME/.config/polybar"
link_file "$DOTFILES_DIR/config/rofi" "$HOME/.config/rofi" link_file "$DOTFILES_DIR/config/rofi" "$HOME/.config/rofi"
link_file "$DOTFILES_DIR/config/nvim" "$HOME/.config/nvim"
link_file "$DOTFILES_DIR/scripts/bin" "$HOME/.local/bin"
echo "" echo ""
echo "🧾 Summary: $CREATED symlink(s) created or fixed, $SKIPPED skipped." echo "🧾 Summary: $CREATED symlink(s) created or fixed, $SKIPPED skipped."
@@ -162,7 +161,7 @@ if [ "$DO_INSTALL" = true ]; then
# system # system
pfetch fuse pfetch fuse
# window manager & desktop # window manager & desktop
xdotool wmctrl polybar rofi kanata picom xdotool wmctrl polybar rofi kanata
# fonts # fonts
noto-fonts-ttf noto-fonts-emoji noto-fonts-ttf noto-fonts-emoji
) )
@@ -193,10 +192,10 @@ if [ "$DO_INSTALL" = true ]; then
echo "✅ Package setup complete." echo "✅ Package setup complete."
echo "" echo ""
fi fi
# TODO: these need to go somewhere! # TODO: these need to go somewhere!
# xfconf-query -c xfce4-session -np '/shutdown/ShowSuspend' -t 'bool' -s 'false' # xfconf-query -c xfce4-session -np '/shutdown/ShowSuspend' -t 'bool' -s 'false'
# xfconf-query -c xfce4-session -np '/shutdown/ShowHibernate' -t 'bool' -s 'false' # xfconf-query -c xfce4-session -np '/shutdown/ShowHibernate' -t 'bool' -s 'false'
# xfconf-query -c xfce4-session -np '/shutdown/ShowHybridSleep' -t 'bool' -s 'false' # xfconf-query -c xfce4-session -np '/shutdown/ShowHybridSleep' -t 'bool' -s 'false'
# xfconf-query -c xfce4-session -np '/shutdown/ShowSwitchUser' -t 'bool' -s 'false' # xfconf-query -c xfce4-session -np '/shutdown/ShowSwitchUser' -t 'bool' -s 'false'
# xfconf-query -c xfwm4 -p /general/placement_ratio -s 100 # xfconf-query -c xfwm4 -p /general/placement_ratio -s 100
# xfconf-query -c xfwm4 -p /general/use_compositing -s false
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
# Nothing to clean for the previewer above, but lf requires this script.
exit 0
+17
View File
@@ -0,0 +1,17 @@
#!/bin/sh
for file in "$@"; do
case "$file" in
*.tar) tar xvf "$file" ;;
*.tar.gz|*.tgz) tar xzvf "$file" ;;
*.tar.bz2|*.tbz2) tar xjvf "$file" ;;
*.tar.xz|*.txz) tar xJvf "$file" ;;
*.zip) unzip "$file" ;;
*.rar) unrar x "$file" ;;
*.7z) 7z x "$file" ;;
*.gz) gunzip "$file" ;;
*.bz2) bunzip2 "$file" ;;
*.xz) unxz "$file" ;;
*) echo "Unknown archive type: $file" ;;
esac
done
+30
View File
@@ -0,0 +1,30 @@
#!/bin/sh
file="$1"
w="$2"
h="$3"
case "$(file -Lb --mime-type "$file")" in
text/*|application/json|application/x-empty|inode/x-empty)
bat --theme="ansi" --color=always --style=numbers --line-range=:500 --terminal-width="$w" "$file"
;;
image/*)
echo "Image: $file"
;;
application/pdf)
pdftotext -l 10 -nopgbrk -q "$file" - | fold -s -w "$w"
;;
application/zip|application/x-tar|application/x-rar|application/x-7z-compressed|application/gzip|application/x-bzip2|application/x-xz)
echo "Archive: $file"
echo
case "$file" in
*.zip) unzip -l "$file" ;;
*.tar|*.tar.*|*.tgz) tar tf "$file" ;;
*.rar) unrar l "$file" ;;
*.7z) 7z l "$file" ;;
*) echo "Archive listing not supported" ;;
esac
;;
*)
file -Lb "$file"
;;
esac
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
/usr/bin/alacritty &
sleep 0.1
# xdotool windowactivate
/home/jason/.local/bin/tile
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
/usr/bin/chromium --password-store=basic &
sleep 0.4
# xdotool windowactivate
/home/jason/.local/bin/tile
+200
View File
@@ -0,0 +1,200 @@
#!/bin/bash
set -e
# --- CONFIG ---
TOP_BAR=36
DECOR_H=30
DECOR_W=5
MASTER_RATIO_NUM=1
MASTER_RATIO_DEN=2
OUTER_GAP=8
INNER_GAP=8
# Master selection:
# focused = currently focused window
# first = first window on desktop
# last = last window on desktop
MASTER_MODE="focused"
# ----------------
# Get current screen resolution
read SCREEN_W SCREEN_H <<< $(xrandr | awk '
/\*/ {
split($1,a,"x")
print a[1], a[2]
exit
}')
USABLE_H=$((SCREEN_H - TOP_BAR))
# Work area after outer gaps
WORK_X=$OUTER_GAP
WORK_Y=$((TOP_BAR + OUTER_GAP))
WORK_W=$((SCREEN_W - 2 * OUTER_GAP))
WORK_H=$((USABLE_H - 2 * OUTER_GAP))
# --- focused window ---
FOCUSED=$(printf "0x%08x" "$(xdotool getactivewindow)")
# --- current desktop ---
CUR_DESKTOP=$(xdotool get_desktop)
# --- collect windows on current desktop ---
ALL_WINDOWS=$(wmctrl -l -x | awk '$2!="-1" {print $1}')
WINDOWS=()
for w in $ALL_WINDOWS; do
win_desktop=$(xdotool get_desktop_for_window "$(printf "%d" "$w")" 2>/dev/null) || continue
if [ "$win_desktop" = "$CUR_DESKTOP" ]; then
WINDOWS+=("$w")
fi
done
if [ ${#WINDOWS[@]} -eq 0 ]; then
echo "No windows found on current desktop."
exit 1
fi
# ----------------------------------------------------
# Determine master window
# ----------------------------------------------------
case "$MASTER_MODE" in
focused)
MASTER="$FOCUSED"
;;
first)
MASTER="${WINDOWS[0]}"
;;
last)
MASTER="${WINDOWS[$((${#WINDOWS[@]} - 1))]}"
;;
*)
echo "Invalid MASTER_MODE: $MASTER_MODE"
exit 1
;;
esac
# --- separate master from stack ---
STACK=()
for w in "${WINDOWS[@]}"; do
if [ "$w" != "$MASTER" ]; then
STACK+=("$w")
fi
done
place() {
local id=$1
local x=$2
local y=$3
local raw_w=$4
local raw_h=$5
local class decor_h decor_w x_offset y_offset
x_offset=0
y_offset=0
class=$(xprop -id "$id" WM_CLASS 2>/dev/null | sed -r 's/.*"(.*)"$/\1/')
case "$class" in
Alacritty)
decor_h=42
decor_w=8
;;
Chromium)
decor_h=42
decor_w=5
;;
obsidian)
decor_h=5
decor_w=0
x_offset=-0
y_offset=-0
;;
dev.zed.Zed)
decor_h=-19
decor_w=-23
x_offset=-13
y_offset=-13
;;
*)
decor_h=$DECOR_H
decor_w=$DECOR_W
;;
esac
local w=$((raw_w - decor_w))
local h=$((raw_h - decor_h))
local fx=$((x + x_offset))
local fy=$((y + y_offset))
wmctrl -i -r "$id" -b remove,maximized_vert,maximized_horz
wmctrl -i -r "$id" -e 1,"$fx","$fy","$w","$h"
}
# ----------------------------------------------------
# Single window
# ----------------------------------------------------
if [ ${#WINDOWS[@]} -eq 1 ]; then
place \
"$MASTER" \
"$WORK_X" \
"$WORK_Y" \
"$WORK_W" \
"$WORK_H"
exit 0
fi
# ----------------------------------------------------
# Master / Stack layout
# ----------------------------------------------------
MID=$((WORK_W * MASTER_RATIO_NUM / MASTER_RATIO_DEN))
MASTER_X=$WORK_X
MASTER_Y=$WORK_Y
MASTER_W=$((MID - INNER_GAP / 2))
MASTER_H=$WORK_H
STACK_X=$((WORK_X + MID + INNER_GAP / 2))
STACK_Y=$WORK_Y
STACK_W=$((WORK_W - MID - INNER_GAP / 2))
STACK_H=$WORK_H
# --- place master ---
place \
"$MASTER" \
"$MASTER_X" \
"$MASTER_Y" \
"$MASTER_W" \
"$MASTER_H"
# --- place stack ---
COUNT=${#STACK[@]}
if [ "$COUNT" -gt 0 ]; then
SLOT_H=$(((STACK_H - INNER_GAP * (COUNT - 1)) / COUNT))
i=0
for w in "${STACK[@]}"; do
SLOT_Y=$((STACK_Y + i * (SLOT_H + INNER_GAP)))
place \
"$w" \
"$STACK_X" \
"$SLOT_Y" \
"$STACK_W" \
"$SLOT_H"
i=$((i + 1))
done
fi
+78
View File
@@ -0,0 +1,78 @@
#!/bin/bash
# focus-dir.sh - focus the nearest window in a given direction (h/j/k/l)
# Usage: focus-dir.sh h|j|k|l (or left/down/up/right)
DIR=$1
if [ -z "$DIR" ]; then
echo "Usage: $0 h|j|k|l"
exit 1
fi
# --- get current desktop ---
CUR_DESKTOP=$(xdotool get_desktop)
# --- get focused window geometry ---
FOCUSED=$(xdotool getactivewindow)
read -r FX FY FW FH < <(xdotool getwindowgeometry --shell "$FOCUSED" | awk -F= '
/^X=/ {x=$2} /^Y=/ {y=$2} /^WIDTH=/ {w=$2} /^HEIGHT=/ {h=$2}
END {print x, y, w, h}
')
FCX=$((FX + FW / 2))
FCY=$((FY + FH / 2))
# --- get list of normal windows on current desktop ---
ALL_WINDOWS=$(wmctrl -l -x | awk '$2!="-1" {print $1}')
BEST=""
BEST_DIST=""
for w in $ALL_WINDOWS; do
wid=$(printf "%d" "$w")
[ "$wid" = "$FOCUSED" ] && continue
win_desktop=$(xdotool get_desktop_for_window "$wid" 2>/dev/null) || continue
[ "$win_desktop" = "$CUR_DESKTOP" ] || continue
read -r WX WY WW WH < <(xdotool getwindowgeometry --shell "$wid" | awk -F= '
/^X=/ {x=$2} /^Y=/ {y=$2} /^WIDTH=/ {w=$2} /^HEIGHT=/ {h=$2}
END {print x, y, w, h}
')
WCX=$((WX + WW / 2))
WCY=$((WY + WH / 2))
DX=$((WCX - FCX))
DY=$((WCY - FCY))
case "$DIR" in
h|left)
[ "$DX" -ge 0 ] && continue
;;
l|right)
[ "$DX" -le 0 ] && continue
;;
k|up)
[ "$DY" -ge 0 ] && continue
;;
j|down)
[ "$DY" -le 0 ] && continue
;;
*)
echo "Invalid direction: $DIR"
exit 1
;;
esac
# Manhattan distance, weighted to prefer windows roughly in line
DIST=$(( (DX<0?-DX:DX) + (DY<0?-DY:DY) ))
if [ -z "$BEST_DIST" ] || [ "$DIST" -lt "$BEST_DIST" ]; then
BEST_DIST=$DIST
BEST=$wid
fi
done
if [ -n "$BEST" ]; then
xdotool windowactivate "$BEST"
fi