Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: better integration with sketchybar #175

Open
regisverdin opened this issue Mar 3, 2024 · 3 comments
Open

Question: better integration with sketchybar #175

regisverdin opened this issue Mar 3, 2024 · 3 comments

Comments

@regisverdin
Copy link

Hey there. I've been trying to build a proper dock-like menu bar for aerospace using sketchybar, and have run into some issues. I'm posting this in the hopes that someone else has tried this with more success, or has some suggestions. This is where I got:

Screenshot 2024-03-03 at 1 26 56 AM

It should support the following:

  • highlight active app.
  • highlight active workspace.
  • order apps in a somewhat sensible way (l-r, top-bottom)
  • update when creating/closing a window
  • update when moving windows left/right within a workspace.
  • update when moving windows between workspaces.

My impression is that there should be a better integration between aerospace and sketchybar, or else aerospace should just implement it's own menu bar. The communication between aerospace and sketchybar here is really messy (although I think this is mostly on sketchybar's side... it's very hard to manage state in sketchybar)

I think this would be a really useful tool to have, especially for users with many workspaces who want a quick way to keep track of what is where.

Here are my config files I hacked together. This is as far as I got before giving up.


aerospace.toml:

# 'start-at-login' needs to be 'true' for 'after-login-command' to work
# Available commands: https://nikitabobko.github.io/AeroSpace/commands.html
after-login-command = []

# You can use it to add commands that run after AeroSpace startup.
# 'after-startup-command' is run after 'after-login-command'
# Available commands : https://nikitabobko.github.io/AeroSpace/commands.html
after-startup-command = [
    # JankyBorders has a built-in detection of already running process,
    # so it won't be run twice on AeroSpace restart
    'exec-and-forget borders',
    # 'exec-and-forget /opt/homebrew/opt/sketchybar/bin/sketchybar'
]


[[on-window-detected]]
run = ['/bin/bash -c /opt/homebrew/opt/sketchybar/bin/sketchybar --trigger new-window']

# Notify Sketchybar about workspace change
# exec-on-workspace-change = [
#     '/bin/bash',
#     '-c',
#     '/opt/homebrew/opt/sketchybar/bin/sketchybar --trigger change-focused-workspace FOCUSED=$AEROSPACE_FOCUSED_WORKSPACE PREV_FOCUSED=$AEROSPACE_PREV_WORKSPACE',
# ]


# Start AeroSpace at login
start-at-login = false

# Normalizations. See: https://nikitabobko.github.io/AeroSpace/guide.html#normalization
enable-normalization-flatten-containers = true
enable-normalization-opposite-orientation-for-nested-containers = true

# See: https://nikitabobko.github.io/AeroSpace/guide.html#layouts
# The 'accordion-padding' specifies the size of accordion padding
# You can set 0 to disable the padding feature
accordion-padding = 30

# Possible values: tiles|accordion
default-root-container-layout = 'tiles'

# Possible values: horizontal|vertical|auto
# 'auto' means: wide monitor (anything wider than high) gets horizontal orientation,
#               tall monitor (anything higher than wide) gets vertical orientation
default-root-container-orientation = 'auto'

# Gaps between windows (inner-*) and between monitor edges (outer-*).
# Possible values:
# - Constant:     gaps.outer.top = 8
# - Per monitor:  gaps.outer.top = [{ monitor.main = 16 }, { monitor."some-pattern" = 32 }, 24]
#                 In this example, 24 is a default value when there is no match.
#                 Monitor pattern is the same as for 'workspace-to-monitor-force-assignment'.
#                 See: https://nikitabobko.github.io/AeroSpace/guide.html#assign-workspaces-to-monitors


gaps.inner.horizontal = [
    { monitor."built-in" = 10 },
    { monitor."LG Ultra HD" = 12 },
    10,
]
gaps.inner.vertical = [
    { monitor."built-in" = 10 },
    { monitor."LG Ultra HD" = 12 },
    10,
]
gaps.outer.left = [
    { monitor."built-in" = 30 },
    { monitor."LG Ultra HD" = 30 },
    10,
]
gaps.outer.bottom = [
    { monitor."built-in" = 10 },
    { monitor."LG Ultra HD" = 30 },
    10,
]
gaps.outer.top = [
    { monitor."built-in" = 10 },
    { monitor."LG Ultra HD" = 60 },
    30,
]
gaps.outer.right = [
    { monitor."built-in" = 10 },
    { monitor."LG Ultra HD" = 30 },
    10,
]

# Visual indent makes it easier to understand that containers of the same orientation are nested.
# If you have 'enable-normalization-opposite-orientation-for-nested-containers' enabled then
# there is no way to observe the indent
indent-for-nested-containers-with-the-same-orientation = 30

# 'main' binding mode declaration
# See: https://nikitabobko.github.io/AeroSpace/guide.html#binding-modes
# 'main' binding mode must be always presented
[mode.main.binding]

# All possible keys:
# - Letters.        a, b, c, ..., z
# - Numbers.        0, 1, 2, ..., 9
# - Keypad numbers. keypad0, keypad1, keypad2, ..., keypad9
# - F-keys.         f1, f2, ..., f20
# - Special keys.   minus, equal, period, comma, slash, backslash, quote, semicolon, backtick,
#                   leftSquareBracket, rightSquareBracket, space, enter, esc, backspace, tab
# - Keypad special. keypadClear, keypadDecimalMark, keypadDivide, keypadEnter, keypadEqual,
#                   keypadMinus, keypadMultiply, keypadPlus
# - Arrows.         left, down, up, right

# All possible modifiers: cmd, alt, ctrl, shift

# All possible commands: https://nikitabobko.github.io/AeroSpace/commands.html

# See: https://nikitabobko.github.io/AeroSpace/commands.html#layout
alt-slash = 'layout tiles horizontal vertical'
alt-comma = 'layout accordion horizontal vertical'

# See: https://nikitabobko.github.io/AeroSpace/commands.html#focus
alt-h = ['focus left', 'exec-and-forget sketchybar --trigger change-focused-window']
alt-j = ['focus down', 'exec-and-forget sketchybar --trigger change-focused-window']
alt-k = ['focus up', 'exec-and-forget sketchybar --trigger change-focused-window']
alt-l = ['focus right', 'exec-and-forget sketchybar --trigger change-focused-window']

alt-ctrl-f = 'fullscreen'

# See: https://nikitabobko.github.io/AeroSpace/commands.html#move
alt-shift-h = ['move left', 'exec-and-forget sketchybar --trigger move-window']
alt-shift-j = ['move down', 'exec-and-forget sketchybar --trigger move-window']
alt-shift-k = ['move up', 'exec-and-forget sketchybar --trigger move-window']
alt-shift-l = ['move right', 'exec-and-forget sketchybar --trigger move-window']

# See: https://nikitabobko.github.io/AeroSpace/commands.html#resize
alt-shift-minus = 'resize smart -50'
alt-shift-equal = 'resize smart +50'

# See: https://nikitabobko.github.io/AeroSpace/commands.html#workspace
alt-y = ['workspace 0', 'exec-and-forget sketchybar --trigger change-focused-workspace']
alt-u = ['workspace 1', 'exec-and-forget sketchybar --trigger change-focused-workspace']
alt-i = ['workspace 2', 'exec-and-forget sketchybar --trigger change-focused-workspace']
alt-o = ['workspace 3', 'exec-and-forget sketchybar --trigger change-focused-workspace']
alt-p = ['workspace 4', 'exec-and-forget sketchybar --trigger change-focused-workspace']


# See: https://nikitabobko.github.io/AeroSpace/commands.html#move-node-to-workspace
alt-shift-y = ['move-node-to-workspace 0', 'exec-and-forget sketchybar --trigger move-window']
alt-shift-u = ['move-node-to-workspace 1', 'exec-and-forget sketchybar --trigger move-window']
alt-shift-i = ['move-node-to-workspace 2', 'exec-and-forget sketchybar --trigger move-window']
alt-shift-o = ['move-node-to-workspace 3', 'exec-and-forget sketchybar --trigger move-window']
alt-shift-p = ['move-node-to-workspace 4', 'exec-and-forget sketchybar --trigger move-window']

# See: https://nikitabobko.github.io/AeroSpace/commands.html#workspace-back-and-forth
alt-tab = 'workspace-back-and-forth'
# See: https://nikitabobko.github.io/AeroSpace/commands.html#move-workspace-to-monitor
alt-shift-tab = 'move-workspace-to-monitor --wrap-around next'

# See: https://nikitabobko.github.io/AeroSpace/commands.html#mode
alt-shift-semicolon = 'mode service'
alt-shift-slash = 'mode join'

# 'service' binding mode declaration.
# See: https://nikitabobko.github.io/AeroSpace/guide.html#binding-modes
[mode.service.binding]
r = ['flatten-workspace-tree', 'mode main'] # reset layout
#s = ['layout sticky tiling', 'mode main'] # sticky is not yet supported https://github.com/nikitabobko/AeroSpace/issues/2
f = [
    'layout floating tiling',
    'mode main',
] # Toggle between floating and tiling layout
backspace = ['close-all-windows-but-current', 'mode main']
esc = ['reload-config', 'mode main']

# 'join' binding mode declaration
# See: https://nikitabobko.github.io/AeroSpace/guide.html#binding-modes
[mode.join.binding]
alt-shift-h = ['join-with left', 'mode main']
alt-shift-j = ['join-with down', 'mode main']
alt-shift-k = ['join-with up', 'mode main']
alt-shift-l = ['join-with right', 'mode main']
esc = 'mode main'

sketchybarrc:

#! /bin/bash

source ~/.config/sketchybar/sketchybar-app-font/dist/icon_map.sh

PLUGIN_DIR="$CONFIG_DIR/plugins"

BAR_COLOR=0xff22202b
MAIN_COLOR=0xffa17fa7
ACCENT_COLOR=0xffe19286

bar=(
  height=32
  # color=$BAR_COLOR
  color=0x000000
  # border_color=$MAIN_COLOR
  # border_width=1
  # corner_radius=10
  shadow=off
  position=top
  sticky=on
  padding_right=10
  padding_left=10
  y_offset=5
  margin=15
  notch_width=0
)

sketchybar --bar "${bar[@]}"

default=(
  padding_left=5
  padding_right=5
  label.font="Hack Nerd Font:Bold:14.0"
  icon.color=$MAIN_COLOR
  label.color=$MAIN_COLOR
  icon.padding_left=4
  icon.padding_right=4
  label.padding_left=4
  label.padding_right=4
)

sketchybar --default "${default[@]}"

sketchybar --add event aerospace-workspace-change
sketchybar --add event change-focused-workspace
sketchybar --add event change-focused-window
sketchybar --add event move-window-within-workspace
sketchybar --add event change-workspace


for sid in $(aerospace list-workspaces --all); do
  label=(
    label="$sid"
    label.color=$MAIN_COLOR
    label.padding_right=13
    script="$CONFIG_DIR/plugins/aerospace.sh change-focused-workspace $sid"
  )
  sketchybar --add item label.$sid left \
    --subscribe label.$sid change-focused-workspace \
    --set label.$sid "${label[@]}"

  icons=()
  while IFS= read -r line; do

    window_id=$(echo $line | awk -F ' \\| ' '{print $1}')
    icons+=("icon.$window_id")

    #this is to set the focused window a highlighted color
    # focused_window_info=$(aerospace list-windows --focused)
    focused_window_id=$(echo $focused_window_info | awk -F ' \\| ' '{print $1}')
    # echo $focused_window_id
    if [ "$window_id" = "$focused_window_id" ]; then
        icon_color=$ACCENT_COLOR
    else
        icon_color=$MAIN_COLOR
    fi
    # echo $icon_color
    

    app_name=$(echo $line | awk -F ' \\| ' '{print $2}')
    __icon_map "${app_name}"

    icon=(
      icon="${icon_result}"
      icon.font="sketchybar-app-font:Regular:20.0"
      icon.color="$icon_color"
      label.align=center
      click_script="aerospace workspace $sid"
      script="$CONFIG_DIR/plugins/aerospace.sh change-focused-window $window_id"
    )

    sketchybar --add item icon.$window_id left \
      --subscribe icon.$window_id change-focused-workspace change-focused-window \
      --set icon.$window_id "${icon[@]}"
  done < <(aerospace list-windows --workspace "$sid")

  echo ${icons[@]}
  space=(
    background.height=26
    background.corner_radius=4
    background.border_color=$MAIN_COLOR
    background.border_width=1
    background.color=0x00000000
    script="$CONFIG_DIR/plugins/aerospace.sh create-delete-window"
  )
  sketchybar --add bracket space.$sid label.$sid ${icons[@]} \
    --subscribe space.$sid space_windows_change \
    --set space.$sid "${space[@]}"

done

sketchybar --add item clock right \
           --set clock update_freq=10 icon=  script="$PLUGIN_DIR/clock.sh" \
           --add item volume right \
           --set volume script="$PLUGIN_DIR/volume.sh" \
           --subscribe volume volume_change \
           --add item battery right \
           --set battery update_freq=120 script="$PLUGIN_DIR/battery.sh" \
           --subscribe battery system_woke power_source_change

##### Force all scripts to run the first time (never do this in a script) #####
# sketchybar --update

aerospace.sh:

#!/usr/bin/env bash

MAIN_COLOR=0xffa17fa7
ACCENT_COLOR=0xffe19286

if [ "$1" = "change-focused-window" ]; then
    echo "change-focused-window"
    focused_window_info=$(aerospace list-windows --focused)
    focused_window_id=$(echo $focused_window_info | awk -F ' \\| ' '{print $1}')
    if [ "$2" = "$focused_window_id" ]; then
        sketchybar --set $NAME icon.color=$ACCENT_COLOR
    else
        sketchybar --set $NAME icon.color=$MAIN_COLOR
    fi
fi

if [ "$1" = "change-focused-workspace" ]; then
    echo "change-focused-workspace"
    focused_workspace=$(aerospace list-workspaces --focused)
    if [ "$2" = "$focused_workspace" ]; then
        sketchybar --set $NAME label.color=$ACCENT_COLOR
    else
        sketchybar --set $NAME label.color=$MAIN_COLOR
    fi
fi

if [ "$1" = "move-window-within-workspace" ]; then
    echo "move-window-within-workspace"
    focused_workspace=$(aerospace list-workspaces --focused)
    if [ "$2" = "$focused_workspace" ]; then
        sketchybar --set $NAME label.color=$ACCENT_COLOR
    else
        sketchybar --set $NAME label.color=$MAIN_COLOR
    fi
fi


if [ "$1" = "create-delete-window" ]; then
    echo "create-delete"
    apps_in_window=$(aerospace list-windows --workspace $(aerospace list-workspaces --focused))
    # echo $apps_in_window
    # echo $INFO

    #USE A REGEX IN SKETCHYBAR. Prefix all your icons with their window id.
    sketchybar --remove /icon./
    sketchybar --remove /label./
    sketchybar --remove /space./

    # #Re-render all app icons in all workspaces
    source ~/.config/sketchybar/sketchybar-app-font/dist/icon_map.sh

    PLUGIN_DIR="$CONFIG_DIR/plugins"

    BAR_COLOR=0xff22202b
    MAIN_COLOR=0xffa17fa7
    ACCENT_COLOR=0xffe19286
    default=(
    padding_left=5
    padding_right=5
    label.font="Hack Nerd Font:Bold:14.0"
    icon.color=$MAIN_COLOR
    label.color=$MAIN_COLOR
    icon.padding_left=4
    icon.padding_right=4
    label.padding_left=4
    label.padding_right=4
    )

    sketchybar --default "${default[@]}"

    for sid in $(aerospace list-workspaces --all); do
        label=(
            label="$sid"
            label.color=$MAIN_COLOR
            label.padding_right=13
            script="$CONFIG_DIR/plugins/aerospace.sh change-focused-workspace $sid"
        )
        sketchybar --add item label.$sid left \
            --subscribe label.$sid change-focused-workspace \
            --set label.$sid "${label[@]}"

        icons=()
        while IFS= read -r line; do
            window_id=$(echo $line | awk -F ' \\| ' '{print $1}')
            icons+=("icon.$window_id")

            app_name=$(echo $line | awk -F ' \\| ' '{print $2}')
            __icon_map "${app_name}"

            icon=(
            icon="${icon_result}"
            icon.font="sketchybar-app-font:Regular:20.0"
            label.align=center
            click_script="aerospace workspace $sid"
            script="$CONFIG_DIR/plugins/aerospace.sh change-focused-window $window_id"
            )

            sketchybar --add item icon.$window_id left \
            --subscribe icon.$window_id change-focused-workspace change-focused-window \
            --set icon.$window_id "${icon[@]}"
        done < <(aerospace list-windows --workspace "$sid")

        # echo ${icons[@]}
        space=(
            background.height=26
            background.corner_radius=4
            background.border_color=$MAIN_COLOR
            background.border_width=1
            background.color=0x00000000
            script="$CONFIG_DIR/plugins/aerospace.sh create-delete-window"
        )
        sketchybar --add bracket space.$sid label.$sid ${icons[@]} \
            --subscribe space.$sid space_windows_change \
            --set space.$sid "${space[@]}"

    done

fi

#also need MOVE window. get the order from aerospace list-windows --workspace. bind the "move" aerospace commands in aerospace.toml to exec 'sketchybar --trigger ...'.
@nikitabobko
Copy link
Owner

aerospace list-windows --workspace $(aerospace list-workspaces --focused)

This can be simplified to: aerospace list-windows --workspace focused


However, I can't help you with sketchybar integration, since I don't use any bars. Hopefully, somebody else can

@nikitabobko nikitabobko changed the title [Feature Request] Full example of sketchybar integration Question: better integration with sketchybar Mar 3, 2024
@jakufort
Copy link

jakufort commented Mar 4, 2024

(piggybacking on this question, since this is in the same area :) )

I use exec-on-workspace-change to propagate "workspace-changed" event to sketchybar which let's me to change active workspace and change window title.
Is there any event to detect when window title changes? For example, when I change tab.
I haven't seen anything that would fit, but I might be missing something.

(I thought that it's something that could be solved by on-window-detected, but exec-and-forget command is not accepted in run)

@nikitabobko
Copy link
Owner

nikitabobko commented Mar 4, 2024

I thought that it's something that could be solved by on-window-detected, but exec-and-forget command is not accepted in run

on-window-detected is not invoked on the window's title changes, so allowing exec-and-forget in on-window-detected won't help here

Currently AeroSpace doesn't listen for "window changed title" events. I see that there is an API for it, so technically it should be possible. Tracking issue: #177

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants