v0.1.11 — Multi-monitor handling: disable an auxiliary monitor before Gaming Mode
Reported on a Framework Desktop (AMD AI MAX 380) + Gigabyte M27Q +
LG DualUp setup: with both monitors attached, gamescope would either
land on the wrong screen or refuse to start, and writing
OUTPUT_CONNECTOR=DP-X alone wasn't enough to fix it. The workaround
shipped by the user was to manually patch /usr/share/gamescope-session-plus
to disable the other monitor before launching gamescope.
DeckShift now handles this natively, without touching the
gamescope-session-plus script (which is ChimeraOS's, not ours):
- New env var OUTPUT_CONNECTOR_TO_DISABLE (single connector or
comma list) written to ~/.config/environment.d/gamescope-session-plus.conf
alongside the other display keys.
- switch-to-gaming reads it and runs `hyprctl keyword monitor X,disable`
for each listed connector BEFORE the SDDM restart, while Hyprland is
still alive (hyprctl needs a live IPC socket). The disable is
runtime-only — Hyprland's static config isn't touched — so when the
user returns from Gaming Mode the new Hyprland reads its config fresh
and the monitor comes back automatically. No re-enable step needed.
- Settings TUI exposes this as a "Hide monitor" main-menu item. The
picker lists every connected monitor EXCEPT the gaming one (so a
user can't accidentally pick the same connector they just set as
OUTPUT_CONNECTOR) and includes a "(clear)" entry.
Also fixes a latent bug in v0.1.10's config-path shortening:
${CONF/#$HOME/~} was supposed to render the conf path with ~ but
bash applies tilde-expansion to the replacement side, re-expanding ~
to $HOME and making the substitution a no-op. Escaped as \~ now.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
aaa2f3d768
commit
52c883b780
+54
-7
@@ -307,7 +307,7 @@ list_gpus() {
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
show_state() {
|
||||
local connector width height refresh vk_adapter dri_prime prime_offload mesa_vk_select
|
||||
local connector width height refresh vk_adapter dri_prime prime_offload mesa_vk_select disable_connector
|
||||
connector=$(effective OUTPUT_CONNECTOR)
|
||||
width=$(effective SCREEN_WIDTH)
|
||||
height=$(effective SCREEN_HEIGHT)
|
||||
@@ -322,6 +322,7 @@ show_state() {
|
||||
dri_prime=$(effective DRI_PRIME)
|
||||
prime_offload=$(effective __NV_PRIME_RENDER_OFFLOAD)
|
||||
mesa_vk_select=$(effective MESA_VK_DEVICE_SELECT)
|
||||
disable_connector=$(effective OUTPUT_CONNECTOR_TO_DISABLE)
|
||||
|
||||
# Single GPU-mode line — shows the active mode rather than half-empty rows,
|
||||
# since the modes are mutually exclusive. AMD hybrid is identified by both
|
||||
@@ -354,7 +355,7 @@ show_state() {
|
||||
fi
|
||||
|
||||
# Replace $HOME with ~ so the config path fits the panel column.
|
||||
local conf_display="${CONF/#$HOME/~}"
|
||||
local conf_display="${CONF/#$HOME/\~}"
|
||||
|
||||
cat <<EOF
|
||||
Gaming Mode display settings${pending_label}
|
||||
@@ -363,6 +364,7 @@ Gaming Mode display settings${pending_label}
|
||||
Resolution : ${resolution_label}
|
||||
Refresh rate : ${refresh:-<auto>} Hz
|
||||
GPU mode : ${gpu_mode}
|
||||
Hide monitor : ${disable_connector:-<none>}
|
||||
|
||||
Config file : ${conf_display}
|
||||
EOF
|
||||
@@ -396,6 +398,49 @@ choose_monitor() {
|
||||
fi
|
||||
}
|
||||
|
||||
# choose_monitor_to_disable — picks a connector to physically disable (via
|
||||
# `hyprctl keyword monitor X,disable`) before Gaming Mode launches.
|
||||
#
|
||||
# Why this exists: with multiple monitors connected, gamescope-session-plus
|
||||
# can't reliably target a single output via OUTPUT_CONNECTOR alone — on some
|
||||
# setups it picks the wrong screen, on others it fails to start at all
|
||||
# (reported on a Framework Desktop + LG DualUp + Gigabyte M27Q setup).
|
||||
# Disabling the auxiliary monitor right before SDDM restart guarantees
|
||||
# gamescope only sees the gaming display.
|
||||
#
|
||||
# The disable is runtime-only (hyprctl keyword, not a config edit), so when
|
||||
# the user returns from Gaming Mode the fresh Hyprland reads its static
|
||||
# config and the monitor comes back automatically — no re-enable step needed.
|
||||
choose_monitor_to_disable() {
|
||||
local choice gaming_monitor
|
||||
gaming_monitor=$(effective OUTPUT_CONNECTOR)
|
||||
mapfile -t connected < <(list_connected_monitors)
|
||||
local -a labels=()
|
||||
local entry conn
|
||||
for entry in "${connected[@]}"; do
|
||||
conn="${entry%%|*}"
|
||||
# Exclude the gaming monitor — disabling it would be self-defeating.
|
||||
[[ "$conn" == "$gaming_monitor" ]] && continue
|
||||
labels+=("$entry")
|
||||
done
|
||||
labels+=("(clear / don't hide any monitor)")
|
||||
if (( ${#labels[@]} == 1 )); then
|
||||
gum confirm "Only the gaming monitor is connected. Set a connector to disable manually?" || return 0
|
||||
local connector
|
||||
connector=$(ginput --prompt "Connector to disable (e.g. HDMI-A-1): ")
|
||||
[[ -z "$connector" ]] && return 0
|
||||
pending_set OUTPUT_CONNECTOR_TO_DISABLE "$connector"
|
||||
return 0
|
||||
fi
|
||||
choice=$(cmenu "Select monitor to disable while gaming" "${labels[@]}")
|
||||
[[ -z "$choice" ]] && return 0
|
||||
if [[ "$choice" == "(clear"* ]]; then
|
||||
pending_unset OUTPUT_CONNECTOR_TO_DISABLE
|
||||
else
|
||||
pending_set OUTPUT_CONNECTOR_TO_DISABLE "${choice%%|*}"
|
||||
fi
|
||||
}
|
||||
|
||||
choose_resolution() {
|
||||
refresh_monitor_data
|
||||
local choice w h
|
||||
@@ -699,13 +744,15 @@ main() {
|
||||
"Resolution" \
|
||||
"Refresh rate" \
|
||||
"GPU" \
|
||||
"Hide monitor" \
|
||||
"$save_label" \
|
||||
"$cancel_label")
|
||||
case "$action" in
|
||||
"Monitor") choose_monitor ;;
|
||||
"Resolution") choose_resolution ;;
|
||||
"Refresh rate") choose_refresh_rate ;;
|
||||
"GPU") choose_gpu ;;
|
||||
"Monitor") choose_monitor ;;
|
||||
"Resolution") choose_resolution ;;
|
||||
"Refresh rate") choose_refresh_rate ;;
|
||||
"GPU") choose_gpu ;;
|
||||
"Hide monitor") choose_monitor_to_disable ;;
|
||||
"Save and exit"*)
|
||||
if ! confirm_risky_save; then
|
||||
continue
|
||||
@@ -713,7 +760,7 @@ main() {
|
||||
flush_pending
|
||||
clear
|
||||
echo ""
|
||||
gum style --foreground 212 "Settings saved to ${CONF/#$HOME/~}" | pad_block
|
||||
gum style --foreground 212 "Settings saved to ${CONF/#$HOME/\~}" | pad_block
|
||||
gum style --foreground 244 "Changes apply next time you enter Gaming Mode (Super+Shift+S)." | pad_block
|
||||
sleep 1
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user