#!/bin/sh # Patch `forge` to draw a border on all tiled and unfocused windows # # Idempotent: Re-running on a patched file changes nothing set -eu XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}" WINDOW_JS="$XDG_DATA_HOME/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/window.js" [ -w "$WINDOW_JS" ] || { echo "Not writable or missing: $WINDOW_JS" >&2; exit 1; } grep -q "showUnfocusedBorders" "$WINDOW_JS" && { echo "Already patched"; exit 0; } # Call our method after the focused border is drawn sed -i '/^ updateBorderLayout() {$/,/^ }$/ s|this\.showWindowBorders();|this.showWindowBorders();\n this.showUnfocusedBorders();|' "$WINDOW_JS" # Append the method right after `updateBorderLayout()` awk ' /^ updateBorderLayout\(\) \{$/ { inFn=1 } inFn && /^ \}$/ { print print "" print " showUnfocusedBorders() {" print " if (!this.ext.settings.get_boolean(\"focus-border-toggle\")) return;" print " this.tree.nodeWindows.forEach((nodeWindow) => {" print " let metaWindow = nodeWindow.nodeValue;" print " if (!metaWindow || metaWindow === this.focusMetaWindow) return;" print " if (metaWindow.minimized || metaWindow.is_fullscreen()) return;" print " if (metaWindow.get_workspace() !== global.workspace_manager.get_active_workspace()) return;" print " let maximized = false;" print " try { maximized = metaWindow.is_maximized(); }" print " catch (e) { maximized = metaWindow.get_maximized() === 3; }" print " if (maximized) return;" print " if (nodeWindow.parentNode.isTabbed() || nodeWindow.parentNode.isStacked()) return;" print " let windowActor = metaWindow.get_compositor_private();" print " if (!windowActor || !windowActor.border) return;" print " let border = windowActor.border;" print " border.set_style_class_name(\"window-unfocused-border\");" print " let rect = metaWindow.get_frame_rect();" print " let inset = 3;" print " border.set_size(rect.width + inset * 2, rect.height + inset * 2);" print " border.set_position(rect.x - inset, rect.y - inset);" print " border.show();" print " if (global.window_group && global.window_group.contains(border)) {" print " global.window_group.remove_child(border);" print " global.window_group.insert_child_above(border, windowActor);" print " }" print " });" print " }" inFn=0 next } { print } ' "$WINDOW_JS" > "$WINDOW_JS.tmp" && mv "$WINDOW_JS.tmp" "$WINDOW_JS" echo "Patched: $WINDOW_JS"