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

Opacity toggle for focused window #503

Closed
lucaorio opened this issue May 3, 2020 · 10 comments
Closed

Opacity toggle for focused window #503

lucaorio opened this issue May 3, 2020 · 10 comments
Labels
enhancement New feature or request

Comments

@lucaorio
Copy link

lucaorio commented May 3, 2020

After the removal of window borders I decided to go back to an opacity-based focus.

Is there any way to toggle the opacity of a focused window? Something like:
yabai -m window --toggle opacity

It would be particularly useful when paired with pip or sticky mode: with window_opacity on in the config, cycling between different windows would keep the pip/sticky on top with a decreased opacity.

This can cause some clutter depending on the content of the window that's underneath the floating one: image

@lucaorio
Copy link
Author

lucaorio commented May 4, 2020

I could be wrong, but it also seems like the topmost property could probably benefit from a forced opacity at 1 in pretty much every case scenario!

@koekeishiya
Copy link
Owner

I don't think it makes sense to toggle opacity on/off for specific windows. I think it might be appropriate to add a window --opacity command that when set to a custom value would make the window no longer inherit opacity from the active/normal config settings. That would require some way to reset that override though.

I think an alternative solution, as you mentioned, is to make sure that topmost windows are always kept at 100% opacity, unless specifically told otherwise (using the window rules system).
Maybe this is the better of the two solutions discussed so far.

@koekeishiya koekeishiya added the discussion Discussion label May 9, 2020
@lucaorio
Copy link
Author

I tried the first approach to force the opacity, but I get:

yabai -m window --opacity 1.0
unknown command '--opacity' for domain 'window'

However, I agree that the second solution feels cleaner!

Is there a way to target every topmost windows directly from the config? I couldn't figure out how to achieve this.

@lucaorio
Copy link
Author

@koekeishiya I think I am kind of stuck here. I trigger the script below to:

  • toggling float
  • toggling topmost
  • create a temporary rule to force the opacity

Whenever I remove the rule, the opacity is stuck at 1.0. Even forcing another rule to set its opacity at 0.5 doesn't work anymore.

Am I doing anything wrong here?

#! /usr/bin/env zsh

# get the app name, title, and id of the focused window
app=$(yabai -m query --windows --window | jq -re .app)
title=$(yabai -m query --windows --window | jq -re .title)
id=$(yabai -m query --windows --window | jq -re .id)
topmost=$(yabai -m query --windows --window | jq -re .topmost)

# temporarily create (or remove) a rule to manage its opacity
if [[ "$topmost" = 0 ]]; then
  yabai -m rule --add app="${app}" title="${title}" label="${id}" opacity=1.0
  echo 'rule added'
else
  yabai -m rule --remove "${id}"
  echo 'rule removed'
fi

# toggle floating and topmost layer
yabai -m window --toggle float
yabai -m window --toggle topmost

@koekeishiya
Copy link
Owner

koekeishiya commented Jun 13, 2020

Implemented the first suggestion; new command to set the opacity of a window:

# set the opacity to 50%
yabai -m window --opacity 0.5

# explicitly set the opacity to 100%
yabai -m window --opacity 1.0

# reset the opacity to full OR make it managed by focus changes, if config window_opacity is enabled
yabai -m window --opacity 0.0

Opacity can also be changed by invoking new rules for the same window, after an initial opacity was set previously. The opacity command will also override any opacity that was set previously through a rule or by the focus change in yabai.

Current window opacity is also returned as an attribute 'opacity' in window queries.

@koekeishiya koekeishiya added addressed on master; not released Fixed upstream, but not yet released enhancement New feature or request and removed discussion Discussion labels Jun 13, 2020
@koekeishiya koekeishiya removed the addressed on master; not released Fixed upstream, but not yet released label Jun 13, 2020
@lucaorio
Copy link
Author

This is amazing, @koekeishiya ! Thanks a lot for the addition!

@RobinHoutevelts
Copy link

Just wanted to thank you as well. It's amazing how powerful this is.


I wanted a better Slack client that didn't eat all my RAM so I found Ripcord.
But then I also wanted it to be able to "just sit there" in a corner of my screen so I put it topmost.

But then it bothered me a bit so I wanted to give it some opacity and I stumbled upon this issue.

So with this script I got Ripcord to have opacity when it sits topmost and isn't focused.

Unfocused: https://i.kzen.pro/2020-06-30/15-13-42--FXrnH.png

Focused: https://i.kzen.pro/2020-06-30/15-19-40--stzBE.png

# ~/.yabairc
# Add a signal that sets the opacity of Ripcord based on it's focus
yabai -m signal --add event=application_activated app="(Ripcord)" action='/Users/me/windowmanager/ripcord_opacity'
yabai -m signal --add event=application_deactivated app="(Ripcord)" action='/Users/me/windowmanager/ripcord_opacity'
#!/bin/bash
# /Users/me/windowmanager/ripcord_opacity

RIPCORD_PID=$(yabai -m query --windows | jq -r '.[] | select(.app == "Ripcord").pid' | uniq)
RIPCORD_ID=$(yabai -m query --windows | jq -r '.[] | select((.app == "Ripcord") and (.topmost == 1)).id' | uniq)

if [ -z "$RIPCORD_PID" ] || [ -z "$RIPCORD_ID" ]; then
  # Ripcord isn't open or isn't topmost
  exit 0
fi

if ! yabai -m query --windows \
    | jq -er "map(select((.pid == $RIPCORD_PID) and (.focused == 1))) | length >= 1" >  /dev/null
then
  # Ripcord hasn't any focused windows
  # Set opacity to 0.6
  yabai -m window $RIPCORD_ID --opacity 0.6
  exit 0
fi

# Ripcord is focused, fallback to default opacity settings
yabai -m window $RIPCORD_ID --opacity 0.0
exit 0

@koekeishiya
Copy link
Owner

@RobinHoutevelts

I was actually planning on making something like this for mpv when I play videos on the side, but didn't get around to it yet.
Thanks for sharing your script. I'll be able to make some small edits for it to fit my needs.

@dominiklohmann
Copy link
Collaborator

Love that script @RobinHoutevelts. Here's a version for all topmost floating windows:

#! /usr/bin/env zsh

function topmost_opacity {
  {
    windows="$(yabai -m query --windows)"
    # selectively blacklist apps here, e.g., Alfred
    query='.topmost == 1 and .focused == 0 and .app != "Alfred"'
    jq -n --argjson windows "${windows}" "\$windows[] | select((${query}) | not).id" |
      xargs -I{} yabai -m window {} --opacity 1.0
    jq -n --argjson windows "${windows}" "\$windows[] | select(${query}).id" |
      xargs -I{} yabai -m window {} --opacity 0.9
  } 2>/dev/null
}
yabai -m signal --add event=application_front_switched action="${functions[topmost_opacity]}"
yabai -m signal --add event=window_focused action="${functions[topmost_opacity]}"

@rockyzhang24
Copy link

rockyzhang24 commented Jun 30, 2020

Really helpful, and thank you @dominiklohmann.
BTW, why not use action="topmost_opacity" instead of action="${functions[topmost_opacity]}"?

Update:
Oh, I got the answer: function is local to a shell, so in a subshell the function topmost_opacity is invisible. That's why we have to use ${functions[topmost_opacity]} to extract the whole function body for the subshell to execute.

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

No branches or pull requests

5 participants