aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2026-02-11 10:36:00 -0700
committerJosh Rahm <rahm@google.com>2026-02-11 10:36:00 -0700
commit7f36475e7c5c00da09e9d93f0664d9258e1e8274 (patch)
treeaaf1951476842a05cdc7eb2550c518ee7af3c6d1
parent0099dfdcc56bd6164ea62fddd87ff84c5505613c (diff)
downloadrde-7f36475e7c5c00da09e9d93f0664d9258e1e8274.tar.gz
rde-7f36475e7c5c00da09e9d93f0664d9258e1e8274.tar.bz2
rde-7f36475e7c5c00da09e9d93f0664d9258e1e8274.zip
[feat] implement dragging the "alternate" workspace.HEADmain
-rwxr-xr-xextras/HOME/.local/bin/set-app-volume.sh101
-rwxr-xr-xinstall.sh2
-rw-r--r--src/Main.hs1
-rw-r--r--src/Rahm/Desktop/Dragging.hs14
-rw-r--r--src/Rahm/Desktop/Keys.hs21
5 files changed, 110 insertions, 29 deletions
diff --git a/extras/HOME/.local/bin/set-app-volume.sh b/extras/HOME/.local/bin/set-app-volume.sh
index 8080cca..cc16185 100755
--- a/extras/HOME/.local/bin/set-app-volume.sh
+++ b/extras/HOME/.local/bin/set-app-volume.sh
@@ -4,39 +4,97 @@ set -e
# Best-effort script to control volume of the focused application,
# falling back to the default sink.
+#
+# MODIFIED: Now checks for Spotify and uses 'playerctl' if found.
+# MODIFIED: Pactl branch now matches on process binary name, not PID.
-USAGE="Usage: $(basename "$0") WINDOW_ID [--up | --down]"
+USAGE="Usage: $(basename "$0") WINDOW_ID [--up | --down | --set <0-100>]"
+CHANGE_PCT="5" # Percent to change
# Get the focused window ID
FOCUSED_WIN_ID="$1"
-
shift;
+ACTION=$1
+ARGUMENT=$2
+
+# --- Check if the window is Spotify ---
+IS_SPOTIFY=0
+if [ -n "$FOCUSED_WIN_ID" ] && [ "$FOCUSED_WIN_ID" != "0" ]; then
+ # xprop output is: WM_CLASS(STRING) = "spotify", "Spotify"
+ # We check for "spotify" case-insensitive
+ if xprop -id "$FOCUSED_WIN_ID" WM_CLASS | grep -q -i "spotify"; then
+ IS_SPOTIFY=1
+ fi
+fi
+
+
+# --- BRANCH 1: SPOTIFY LOGIC (use playerctl) ---
+if [ "$IS_SPOTIFY" -eq 1 ]; then
+ echo "Spotify window detected. Using playerctl." >&2
+
+ # playerctl volume is a float from 0.0 to 1.0
+ # We use awk to convert our 5% to 0.05
+ CHANGE_FLOAT=$(awk "BEGIN {print $CHANGE_PCT / 100}")
+
+ case $ACTION in
+ --up)
+ playerctl --player=spotify volume "${CHANGE_FLOAT}+"
+ ;;
+ --down)
+ playerctl --player=spotify volume "${CHANGE_FLOAT}-"
+ ;;
+ --set)
+ # Convert 0-100 input to 0.0-1.0 float
+ TARGET_VOL=$(awk "BEGIN {print $ARGUMENT / 100}")
+ playerctl --player=spotify volume "$TARGET_VOL"
+ ;;
+ *)
+ echo "$USAGE" >&2
+ exit 1
+ ;;
+ esac
+
+ # We are done. Exit successfully.
+ exit 0
+fi
+
+
+# --- BRANCH 2: DEFAULT PACTL LOGIC (if not Spotify) ---
+echo "Non-Spotify window. Using pactl." >&2
+
SINK_INPUT_INDEX=""
if [ -n "$FOCUSED_WIN_ID" ] && [ "$FOCUSED_WIN_ID" != "0" ]; then
# Get the PID of the focused window
PID=$(xprop -id "$FOCUSED_WIN_ID" _NET_WM_PID | awk '{print $NF}')
if [ -n "$PID" ]; then
- # Find PulseAudio sink input index for this PID
- SINK_INPUT_INDEX=$(pactl list sink-inputs | perl -ne '
- BEGIN {
- our $sink_id = -1;
- our $maybe_sink_id = -1;
- }
- if (/Sink Input #(\d+)/) {
- $maybe_sink_id = $1;
- }
- if (/application\.process\.id = "'"$PID"'"/) {
- $sink_id = $maybe_sink_id;
- }
- END { print "$sink_id\n"; }
-')
+ # NEW: Get the binary name from the PID
+ BINARY_NAME=$(ps -p "$PID" -o comm= | tr -d '[:space:]')
+ echo "Looking for binary $BINARY_NAME"
+
+ if [ -n "$BINARY_NAME" ]; then
+ # Find PulseAudio sink input index for this BINARY_NAME
+ # This is more robust than PID for apps like browsers
+ SINK_INPUT_INDEX=$(pactl list sink-inputs | perl -ne '
+ BEGIN {
+ our $sink_id = -1;
+ our $maybe_sink_id = -1;
+ }
+ if (/Sink Input #(\d+)/) {
+ $maybe_sink_id = $1;
+ }
+ # Match the binary name, e.g., application.process.binary = "firefox"
+ if (/application\.process\.binary = "'"$BINARY_NAME"'"/) {
+ $sink_id = $maybe_sink_id;
+ }
+ END { print "$sink_id\n"; }
+ ')
+ fi
fi
fi
-ACTION=$1
-CHANGE="5%"
+CHANGE="${CHANGE_PCT}%"
set_volume() {
local target=$1
@@ -51,7 +109,7 @@ set_volume() {
}
TARGET="@DEFAULT_SINK@"
-if [ -n "$SINK_INPUT_INDEX" -a "$SINK_INPUT_INDEX" -ne -1 ]; then
+if [ -n "$SINK_INPUT_INDEX" ] && [ "$SINK_INPUT_INDEX" -ne -1 ]; then
TARGET="SINK INPUT #$SINK_INPUT_INDEX"
fi
@@ -62,9 +120,14 @@ case $ACTION in
--down)
set_volume "$TARGET" "-$CHANGE"
;;
+ --set)
+ # pactl can take a percentage directly
+ set_volume "$TARGET" "${ARGUMENT}%"
+ ;;
*)
echo "$USAGE" >&2
exit 1
;;
esac
+
diff --git a/install.sh b/install.sh
index f0bfa14..10d0247 100755
--- a/install.sh
+++ b/install.sh
@@ -19,7 +19,7 @@ cc -o \
build/extras/HOME/.xmonad/automonitor \
extras/util/automonitor/automonitor.c \
-ludev
-
+
ln -sf "$(stack path --local-install-root)/bin/xmobar-weather" build/extras/HOME/.xmonad/xmobar-weather
ln -sf "$(stack path --local-install-root)/bin/xmobar-weather" extras/HOME/.xmonad/xmobar-weather
diff --git a/src/Main.hs b/src/Main.hs
index 09810e2..1c67732 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -123,6 +123,7 @@ main = do
className =? "yakuake" --> doFloat,
className =? "MPlayer" --> doFloat,
className =? "zenity" --> doCenterFloat,
+ className =? "gnuplot_qt" --> doCenterFloat,
className =? "Yad" --> doCenterFloat,
className =? "Xfce4-notifyd" --> doIgnore,
className =? "popup-terminal" --> doShift "*" <> updatePopupTerminalHook,
diff --git a/src/Rahm/Desktop/Dragging.hs b/src/Rahm/Desktop/Dragging.hs
index c95deff..1f19290 100644
--- a/src/Rahm/Desktop/Dragging.hs
+++ b/src/Rahm/Desktop/Dragging.hs
@@ -11,7 +11,7 @@ import Data.Maybe (fromMaybe, isJust, mapMaybe)
import qualified Data.Set as Set
import Graphics.X11.Xlib.Extras
import Rahm.Desktop.BorderColors (BorderColor (BorderColor), setBorderColor)
-import Rahm.Desktop.Common (pointerLocation, pointerWindow, runMaybeT_, floatAll)
+import Rahm.Desktop.Common (floatAll, pointerLocation, pointerWindow, runMaybeT_)
import Rahm.Desktop.Layout.Hole (addHoleForWindow, removeHoleForWindow, resetHole)
import Rahm.Desktop.Layout.PinWindow (isWindowPinned, pinWindow, unpinWindow)
import Rahm.Desktop.Logger
@@ -20,6 +20,7 @@ import qualified Rahm.Desktop.StackSet as W
import XMonad (X, io)
import qualified XMonad as X
import XMonad.Util.WindowProperties (getProp32s)
+import Rahm.Desktop.Workspaces (accompanyingWorkspace)
-- Action which happens after a dragging event.
--
@@ -217,6 +218,17 @@ dragWorkspace = do
lift $ X.windows $ W.switchWorkspaces ws1 ws2
+dragAlternateWorkspace :: X ()
+dragAlternateWorkspace = do
+ (ox, oy) <- pointerLocation
+ X.mouseDrag (\_ _ -> return ()) $ do
+ (nx, ny) <- pointerLocation
+ runMaybeT_ $ do
+ (W.Screen (W.tag -> ws1) _ _) <- MaybeT $ X.pointScreen ox oy
+ (W.Screen (W.tag -> ws2) _ _) <- MaybeT $ X.pointScreen nx ny
+
+ lift $ X.windows $ W.switchWorkspaces (accompanyingWorkspace ws1) ws2
+
dragWindow :: X ()
dragWindow = do
w <- pointerWindow
diff --git a/src/Rahm/Desktop/Keys.hs b/src/Rahm/Desktop/Keys.hs
index 1985caf..4a2a426 100644
--- a/src/Rahm/Desktop/Keys.hs
+++ b/src/Rahm/Desktop/Keys.hs
@@ -150,6 +150,8 @@ import XMonad.Layout.Spacing
import XMonad.Util.Run (hPutStrLn, safeSpawn, spawnPipe)
import XMonad.Util.WindowProperties
import Prelude hiding ((!!))
+import Rahm.Desktop.Dragging (windowsUnderCursor)
+import Control.Applicative
type KeyMap l = XConfig l -> Map (KeyMask, KeySym) (X ())
@@ -163,9 +165,13 @@ safeSpawnX = safeSpawn
selectedWindowsColor = BorderColor "#00ffff" "#00ffff"
-decreaseVolume = spawnX "set-app-volume.sh --down"
+decreaseVolume = do
+ wins <- (<|>[0]) <$> windowsUnderCursor
+ spawnX $ printf "set-app-volume.sh %d --down" (head wins)
-increaseVolume = spawnX "set-app-volume.sh --up"
+increaseVolume = do
+ wins <- (<|>[0]) <$> windowsUnderCursor
+ spawnX $ printf "set-app-volume.sh %d --up" (head wins)
playPause = spawnX "media-control play"
@@ -1058,6 +1064,11 @@ bindings = do
doc "Drag a workspace to a different screen" $
noWindow D.dragWorkspace
+ bind button15 $
+ noMod $
+ doc "Drag a workspace to a different screen" $
+ noWindow D.dragAlternateWorkspace
+
bind button1 $
noMod $
doc "Swap a window with another window by dragging." $
@@ -1069,12 +1080,6 @@ bindings = do
noWindow $
click >> sendMessage togglePop
- bind button15 $ do
- noMod $
- doc "Spawn 'pavucontrol'" $
- noWindow $
- spawnX "pavucontrol"
-
let mediaButtons =
[ (button4, "Increase volume", noWindow increaseVolume),
(button5, "Decrease volume", noWindow decreaseVolume),