Reputation:
The native MacOS Terminal
has an ability to set transparency for both in-active and active panes. iTerm2 has the transparency for active backgrounds, for some reason, I can't find the inactive one or maybe there isn't any?
. I am aware that, iTerm2 has the DIM inactive split panes
but what I am looking for is transparency.
Help is appreciated.
Upvotes: 60
Views: 59040
Reputation: 519
Once transparency is enabled, you can toggle transparency on and off with CMD + u.
Upvotes: 1
Reputation: 11
I created a script for anyone that need a script for changing the transparency of the active, and all the inactive, panes/sessions – rather than just for entire windows. It's working both for multiple windows and split panes. Here is the GitHub repo.
Personally I use it in full screen mode with split panes – so I easily can see referance material through the inactive panes, while still keeping the active pane legible.
Feel free to shout out if you got any questions or suggestions, and hope this helps! :)
Edit: Here's the code from the script in the repo mentioned above. Feel free to remove the code using settings.json
– if not, you can create a settings.json file like this in the iTerm2 Scripts folder (/Users/{username}/Library/Application Support/iTerm2/Scripts)
:
{
"pane_transparency": {
"active": 0.2,
"inactive": 0.8,
"blur": false,
"blur_radius": 0
}
}
Can remove the blur stuff if you don't want it as well (have to apply it for every pane, tab and window).
As mentioned above, you can read about how to set up scripts in iTerm2's official documentation. Should run the script as a daemon (from the ./AutoLaunch
folder).
#!/usr/bin/env python3.7
import iterm2
import json
import os
# Global settings
SETTINGS_FILE = os.path.join(os.path.dirname(__file__), '../settings.json')
# Default pane transparency settings (overridden by settings.json)
DEFAULT_TRANSPARENCY_ACTIVE = 0.25
DEFAULT_TRANSPARENCY_INACTIVE = 0.75
DEFAULT_BLUR = False
DEFAULT_BLUR_RADUIUS = 0
async def load_settings():
"""Load settings from the settings.json file."""
with open(SETTINGS_FILE) as f:
settings = json.load(f)
pane_transparency = settings.get("pane_transparency", {})
transparancy_active = pane_transparency.get("active", DEFAULT_TRANSPARENCY_ACTIVE)
transparancy_active = transparancy_active if (0 <= transparancy_active <= 1) else DEFAULT_TRANSPARENCY_ACTIVE
transparency_inactive = pane_transparency.get("inactive", DEFAULT_TRANSPARENCY_INACTIVE)
transparency_inactive = transparency_inactive if (0 <= transparency_inactive <= 1) else DEFAULT_TRANSPARENCY_INACTIVE
blur = pane_transparency.get("blur", DEFAULT_BLUR)
blur = blur if blur == True or False else DEFAULT_BLUR
blur_radius = pane_transparency.get("blur_radius", DEFAULT_BLUR_RADUIUS)
blur_radius = blur_radius if (isinstance(blur_radius, int) and 0 <= blur_radius <= 30) else DEFAULT_BLUR_RADUIUS
return transparancy_active, transparency_inactive, blur, blur_radius
async def transparancy_update(
app,
active_session,
transparency_active,
transparency_inactive,
blur,
blur_radius):
"""Updating the transparency for the active and all inactive panes."""
inactive_change = iterm2.LocalWriteOnlyProfile()
inactive_change.set_transparency(transparency_inactive)
active_change = iterm2.LocalWriteOnlyProfile()
active_change.set_transparency(transparency_active)
active_change.set_blur(blur)
active_change.set_blur_radius(blur_radius)
# Updates all inactive panes
await transparancy_update_inactive(app, active_session, inactive_change)
# Updates the the active pane
await active_session.async_set_profile_properties(active_change)
async def transparancy_update_inactive(app, active_session, inactive_change):
"""Updating the transparency for all inactive panes."""
# Looping over all inactive panes and changing transparency
for window in app.terminal_windows:
for tab in window.tabs:
for session in tab.all_sessions:
if session != active_session:
await session.async_set_profile_properties(inactive_change)
async def main(connection):
"""Pane transparency main method"""
app = await iterm2.async_get_app(connection)
transparency_active, transparency_inactive, blur, blur_radius = await load_settings()
async with iterm2.FocusMonitor(connection) as mon:
active_session = app.current_terminal_window.current_tab.current_session
while True:
update = await mon.async_get_next_update()
if update.active_session_changed:
active_session = app.get_session_by_id(update.active_session_changed.session_id)
if update.active_session_changed or update.selected_tab_changed:
await transparancy_update(
app,
active_session,
transparency_active,
transparency_inactive,
blur,
blur_radius)
iterm2.run_forever(main)
Upvotes: 1
Reputation: 41
Update: I put the two scripts up on GitHub, along with a nice demo GIF :)
Also did a bit of refactor and bug fixing. Check out the repo for the up-to-date scripts.
Each of the previous answers gets a piece of the puzzle. One changes transparency, but is static; the other dims when windows are inactive, rather than changes transparency.
To get the desired behavior (change transparency based on window focus), you need to write a script using iTerm2's Python API, and save it as an AutoLaunch script:
#!/usr/bin/env python3.7
import iterm2
# Store window change event reason objects in more convenient variables
window_selected = [iterm2.FocusUpdateWindowChanged.Reason.TERMINAL_WINDOW_BECAME_KEY]
async def update_tab_transparency(connection, tab, reason):
# Apply to any and all sessions in tab
for session in tab.sessions:
profile = await session.async_get_profile()
change = iterm2.LocalWriteOnlyProfile()
# For window change events bringing a window into focus,
# change transparency to zero
if reason in window_selected:
change.set_transparency(0)
# For window change events taking a window out of focus,
# make sure transparency matches the original profile
else:
# But, only need to do anything if the profile has been changed
# from the original
if profile.original_guid:
original = await iterm2.Profile.async_get(
connection, [profile.original_guid]
)
change.set_transparency(original[0].transparency)
await session.async_set_profile_properties(change)
async def main(connection):
app = await iterm2.async_get_app(connection)
# Initialize for first window
window = app.current_window
if window and window.current_tab:
tab = window.current_tab
reason = window_selected[0]
await update_tab_transparency(connection, tab, reason)
async with iterm2.FocusMonitor(connection) as mon:
while True:
# Block until a tab or window change
update = await mon.async_get_next_update()
# When switching to a new tab, treat as selecting a window
if update.selected_tab_changed:
tab = app.get_tab_by_id(update.selected_tab_changed.tab_id)
reason = window_selected[0]
# For window change events, use the provided event reason
elif update.window_changed:
window = app.get_window_by_id(update.window_changed.window_id)
tab = window.current_tab
reason = update.window_changed.event
# For other focus change events, do nothing
else:
continue
if tab:
await update_tab_transparency(connection, tab, reason)
iterm2.run_forever(main)
See the iTerm docs for details on using Python scripts
You want to set the desired transparency on your profile, and check the "Use transparency" box for "Settings for New Windows". This sounds counter-intuitive, but toggling that "Use transparency" setting doesn't seem to be possible via the API, so the script instead quickly switches windows to opaque on creation.
At least on my machine the window flickers briefly when first selected, but I'm not sure if there's anything I can do about that.
Note: macOS currently (11.6, Big Sur) treats windows the opposite of this—it makes active windows transparent (at least, certain parts of them) and inactive ones opaque (and faded). Try opening a new tab in Safari. It makes sense! The transparency creats a sense of depth. Seeing that there are windows behind the active one emphasizes that it's in front of them.
To get this behavior instead, use the following script. This variant is both simpler, and seems to run more smoothly (no flickering). It works best if you have the blur cranked to max, and transparency ~25.
#!/usr/bin/env python3.7
import iterm2
# Store window change event reason objects in more convenient variables
window_selected = [iterm2.FocusUpdateWindowChanged.Reason.TERMINAL_WINDOW_BECAME_KEY]
async def update_tab_transparency(connection, tab, reason):
# Apply to any and all sessions in tab
for session in tab.sessions:
profile = await session.async_get_profile()
change = iterm2.LocalWriteOnlyProfile()
# For window change events bringing a window into focus,
# make sure transparency matches the original profile
if reason in window_selected:
# But, only need to do anything if the profile has been changed
# from the original
if profile.original_guid:
original = await iterm2.Profile.async_get(
connection, [profile.original_guid]
)
change.set_transparency(original[0].transparency)
# For window change events taking a window out of focus,
# change transparency to zero
else:
change.set_transparency(0)
await session.async_set_profile_properties(change)
async def main(connection):
app = await iterm2.async_get_app(connection)
async with iterm2.FocusMonitor(connection) as mon:
while True:
# Block until a window change
update = await mon.async_get_next_update()
if update.window_changed:
window = app.get_window_by_id(update.window_changed.window_id)
tab = window.current_tab
if tab:
reason = update.window_changed.event
await update_tab_transparency(connection, tab, reason)
iterm2.run_forever(main)
Upvotes: 4
Reputation: 7403
Found the answer on this blog but I'll repeat it here for the sake of preservation.
Upvotes: 102