user5563206
user5563206

Reputation:

iTerm2 Transparent transparent background for inactive windows

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

Answers (5)

Victor Biga
Victor Biga

Reputation: 519

Once transparency is enabled, you can toggle transparency on and off with CMD + u.

Upvotes: 1

BlackZoda
BlackZoda

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

Derrik Petrin
Derrik Petrin

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.

Demo toggling the transparency of two iTerm2 windows


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

bjfletcher
bjfletcher

Reputation: 11518

Preferences → Appearance → Dimming → Dimming amount

enter image description here

Upvotes: 24

Dark Star1
Dark Star1

Reputation: 7403

Found the answer on this blog but I'll repeat it here for the sake of preservation.

  1. Open iTerm2's preferences, using the menu or +,
  2. Select Profiles from the menu bar
  3. Select the Window tab
  4. Drag the transparency slider to suit your needs iTerm2 transparency control

Upvotes: 102

Related Questions