Blog

It's minimal, but I'm posting things.

[KDE] CTRL+T Shortcut: Focus or Launch Konsole + Tmux Per Virtual Desktop

I finally managed to create a KDE shortcut which allows me to open at most one terminal with a Tmux session per virtual desktop1.

I wanted a script that could focus an existing terminal window2 with a specific tmux session or launch a new one if none existed.

It's a tedious and difficult script to implement, so I delegated it to an AI, and it's the first time I had a pleasant result.

Using GPT-5-Codex, I prompted it to write a script that:

  • Checks for existing Konsole windows on the current virtual desktop.
  • Focuses the window if it matches the session name.
  • Otherwise, launches Konsole with a specified profile and creates or attaches a tmux session named after the session.

The first script which was produced worked almost perfectly; in short, there was a bug when identifying the terminal window when my web-browser was already launched on the desktop.

Instead of going back to the expensive GPT-5-Codex, I switched to OpenCode with an orchestrator agent prompt, powered by the much cheaper OpenAI 4.1-mini model.

Then, everything seems to be working great in zsh.

Here's the script which I then bound to a CTRL+T custom shortcut in KDE Plasma.

#!/usr/bin/env bash
: <<'DOC'
Focus Terminal Script
Description:
- This script launches and focuses a Konsole/tmux session based on a session name.
- It attempts to reuse existing Konsole windows on the current virtual desktop via DBus, xdotool, or wmctrl, in that order.
- If no window matches (or only matches on other desktops), it launches Konsole with the given profile and creates/attaches a tmux session named after SESSION.
Usage:
- ./focus-terminal.sh [SESSION] [PROFILE]
- Defaults: SESSION=work, PROFILE="Konsole - Zen"
Exit codes:
- 0 on success
- non-zero on failure
DOC

set -euo pipefail

ENABLE_LOGS=${ENABLE_LOGS:-false}
LOGFILE=./focus-terminal.log

if [ "$ENABLE_LOGS" = "true" ]; then
  mkdir -p "$(dirname "$LOGFILE")"
  touch "$LOGFILE"
  exec >>"$LOGFILE" 2>&1
else
  exec >>/dev/null 2>&1
fi

printf -- '---- %s ----\n' "$(date '+%Y-%m-%d %H:%M:%S')"
printf -- 'Invoked as: %s\n' "$0 $*"

SESSION="${1:-work}"
PROFILE="${2:-Konsole - Zen}"
SEARCH_TERMS=("$SESSION" "$SESSION: " "$SESSION:" "tmux: $SESSION")

CURRENT_DESKTOP=""
DESKTOP_METHOD=""
FOUND_REMOTE_MATCH=false  # No longer used, but kept for compatibility

init_desktop_detection() {
  if command -v xdotool >/dev/null; then
    DESKTOP_METHOD="xdotool"
    CURRENT_DESKTOP=$(xdotool get_desktop 2>/dev/null || true)
  elif command -v wmctrl >/dev/null; then
    DESKTOP_METHOD="wmctrl"
    CURRENT_DESKTOP=$(wmctrl -d | awk '/\*/ {print $1; exit}')
  else
    DESKTOP_METHOD=""
    CURRENT_DESKTOP=""
  fi
}

window_on_current_desktop() {
  local wid="$1"
  local format="${2:-dec}"

  if [ -z "$DESKTOP_METHOD" ] || [ -z "$CURRENT_DESKTOP" ]; then
    return 0
  fi

  if [ "$DESKTOP_METHOD" = "xdotool" ]; then
    local target="$wid"
    if [ "$format" = "hex" ]; then
      if [[ ! "$wid" =~ ^0x[0-9a-fA-F]+$ ]]; then
        return 0
      fi
      target=$((wid))
    fi
    local win_desktop
    win_desktop=$(xdotool get_desktop_for_window "$target" 2>/dev/null || true)
    if [ -z "$win_desktop" ]; then
      return 0
    fi
    [ "$win_desktop" = "$CURRENT_DESKTOP" ]
    return $?
  fi

  if [ "$DESKTOP_METHOD" = "wmctrl" ]; then
    local search_id="$wid"
    if [ "$format" = "dec" ]; then
      if [[ ! "$wid" =~ ^[0-9]+$ ]]; then
        return 0
      fi
      printf -v search_id '0x%08x' "$wid"
    fi
    local win_desktop
    win_desktop=$(wmctrl -l | awk -v id="$search_id" '$1==id {print $2; exit}')
    if [ -z "$win_desktop" ]; then
      return 0
    fi
    [ "$win_desktop" = "$CURRENT_DESKTOP" ]
    return $?
  fi

  return 0
}

init_desktop_detection

TMUX_CONF="$HOME/.tmux.conf"
TMUX_MARK="# focus-terminal managed tmux titles"

if [ -e "$TMUX_CONF" ] && [ ! -w "$TMUX_CONF" ]; then
  echo "Skipping tmux title settings; $TMUX_CONF is not writable"
else
  if [ ! -f "$TMUX_CONF" ] || ! grep -qF "$TMUX_MARK" "$TMUX_CONF" 2>/dev/null; then
    {
      echo ""
      echo "$TMUX_MARK"
      echo "set -g set-titles on"
      echo "set -g set-titles-string '#S: #W'"
      echo "setw -g automatic-rename off"
      echo "setw -g allow-rename off"
    } >>"$TMUX_CONF"
    echo "Ensured tmux title settings in $TMUX_CONF"
  fi
fi

focus_with_dbus() {
  if ! command -v qdbus >/dev/null; then
    echo "qdbus not available; skipping DBus focus"
    return 1
  fi

  if ! qdbus org.kde.konsole >/dev/null 2>&1; then
    echo "Konsole DBus service not running"
    return 1
  fi

  local windows
  windows=$(qdbus org.kde.konsole | awk '/^\/Windows\//')
  if [ -z "$windows" ]; then
    echo "No Konsole windows exposed via DBus"
    return 1
  fi

  local found_other=false
  local win term sess sessions win_title sess_title wid
  for win in $windows; do
    wid=$(qdbus org.kde.konsole "$win" winId 2>/dev/null || true)
    if [ -n "$wid" ] && ! window_on_current_desktop "$wid" "dec"; then
      echo "Skipping $win via DBus; window on different desktop"
      found_other=true
      continue
    fi

    win_title=$(qdbus org.kde.konsole "$win" windowTitle 2>/dev/null || true)
    for term in "${SEARCH_TERMS[@]}"; do
      if [[ -n "$win_title" && "$win_title" == *"$term"* ]]; then
        echo "Focusing $win via DBus windowTitle match '$term'"
        qdbus org.kde.konsole "$win" activateWindow >/dev/null 2>&1 && return 0
      fi
    done

    sessions=$(qdbus org.kde.konsole "$win" sessions 2>/dev/null || true)
    for sess in $sessions; do
      sess_title=$(qdbus org.kde.konsole "$sess" title 2>/dev/null || true)
      for term in "${SEARCH_TERMS[@]}"; do
        if [[ -n "$sess_title" && "$sess_title" == *"$term"* ]]; then
          echo "Focusing $win and session $sess via DBus match '$term'"
          qdbus org.kde.konsole "$win" activateWindow >/dev/null 2>&1 || true
          qdbus org.kde.konsole "$win" setCurrentSession "$sess" >/dev/null 2>&1 || true
          return 0
        fi
      done
    done
  done

  if [ "$found_other" = true ]; then
    return 2
  fi

  return 1
}

focus_with_xdotool() {
  if [ "${XDG_SESSION_TYPE:-x11}" != "x11" ]; then
    echo "Skipping xdotool; session type is ${XDG_SESSION_TYPE:-unknown}"
    return 1
  fi

  if ! command -v xdotool >/dev/null; then
    echo "xdotool not available"
    return 1
  fi

  local desk
  desk=$(xdotool get_desktop 2>/dev/null || true)

  local found_other=false
  local term wid
  for term in "${SEARCH_TERMS[@]}"; do
    if [ -n "$desk" ]; then
      wid=$(xdotool search --desktop "$desk" --class konsole --name "$term" 2>/dev/null | head -n1 || true)
    else
      wid=$(xdotool search --class konsole --name "$term" 2>/dev/null | head -n1 || true)
    fi

    if [ -n "$wid" ]; then
      if ! window_on_current_desktop "$wid" "dec"; then
        echo "Skipping WID=$wid; located on different desktop"
        found_other=true
        continue
      fi
      echo "Focusing WID=$wid via xdotool match '$term'"
      xdotool windowactivate --sync "$wid" && return 0
    fi
  done

  if [ "$found_other" = true ]; then
    return 2
  fi

  return 1
}

focus_with_wmctrl() {
  if ! command -v wmctrl >/dev/null; then
    echo "wmctrl not available"
    return 1
  fi

  local found_other=false
  local line term wid
  while IFS= read -r line; do
    local win_class=$(xprop -id ${line%% *} WM_CLASS 2>/dev/null | awk -F '"' '{print $4}')
    if [[ "$win_class" != "konsole" ]]; then
      continue
    fi
    for term in "${SEARCH_TERMS[@]}"; do
      if [[ "$line" == *"$term"* ]]; then
        wid=${line%% *}
        if [ -n "$wid" ]; then
          if ! window_on_current_desktop "$wid" "hex"; then
            echo "Skipping window $wid; located on different desktop"
            found_other=true
            continue
          fi
          echo "Focusing window $wid via wmctrl match '$term'"
          wmctrl -ia "$wid" && return 0
        fi
      fi
    done
  done < <(wmctrl -l || true)

  if [ "$found_other" = true ]; then
    return 2
  fi

  return 1
}

if focus_with_dbus; then
  exit 0
else
  ret=$?
fi

echo "DBus focus failed; trying xdotool"
if focus_with_xdotool; then
  exit 0
fi

echo "xdotool focus failed; trying wmctrl"
if focus_with_wmctrl; then
  exit 0
fi

echo "No existing Konsole window matched session '$SESSION'"

if ! command -v konsole >/dev/null; then
  echo "konsole binary not found"
  exit 1
fi

SESSION_SAFE=$(printf '%q' "$SESSION")
echo "Launching Konsole for session '$SESSION' with profile '$PROFILE'"
exec konsole \
  --profile "$PROFILE" \
  -p "tabtitle=$SESSION" \
  -e bash -lc "tmux new-session -A -s $SESSION_SAFE"

  1. The script also works accross KDE Activities.

  2. I use KDE Konsole as a terminal emulator.


Published on 2025-10-17T19:44:41.452382Z
Last updated on 2025-10-17T19:44:41.452534Z