aboutsummaryrefslogtreecommitdiffstats
path: root/desktop
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-17 15:56:45 +0200
committerDanilo M. <danix@danix.xyz>2026-10-17 15:56:45 +0200
commit52a2a2dad4b8e35a187b3b287ba32ffafd90b6a4 (patch)
treed2e9afcabce2a4eacaec46669ecd849ce5a68e52 /desktop
parent9989c734c2a0dc8ee3d8074eee961fd01c71a801 (diff)
downloadquickshell-52a2a2dad4b8e35a187b3b287ba32ffafd90b6a4.tar.gz
quickshell-52a2a2dad4b8e35a187b3b287ba32ffafd90b6a4.zip
island: open the window source's properties from the pill
A Wayland window capture is chosen in the portal picker, which only OBS's source dialog can open. In a scene whose only source is a PipeWire capture, the panel gets a Window button that opens that dialog. A window scene with more than one source needs a per-scene designation the pill does not have yet.
Diffstat (limited to 'desktop')
-rw-r--r--desktop/island/Obs.qml9
-rw-r--r--desktop/island/ObsPill.qml15
-rw-r--r--desktop/island/README.md12
3 files changed, 30 insertions, 6 deletions
diff --git a/desktop/island/Obs.qml b/desktop/island/Obs.qml
index 9b8ba06..593e978 100644
--- a/desktop/island/Obs.qml
+++ b/desktop/island/Obs.qml
@@ -34,6 +34,9 @@ Singleton {
property real duration: 0
property var scenes: []
property string scene: ""
+ // The current scene's items as { name, kind }, for the window-source
+ // properties button. Kept current with the same GetSceneItemList call.
+ property var sources: []
// The webcam: the first v4l2_input item in the current scene, -1 for none.
// ponytail: a webcam inside a group or nested scene is not found; walk
// GetGroupSceneItemList if one ever is.
@@ -58,6 +61,10 @@ Singleton {
if (desktopAudio)
request("SetInputMute", { inputName: desktopAudio, inputMuted: !desktopMuted });
}
+ // Opens OBS's source dialog, which is where the Wayland portal picker runs.
+ function openSource(name) {
+ if (name) request("OpenInputPropertiesDialog", { inputName: name });
+ }
// The corner math assumes the webcam item is top-left aligned (alignment 5).
function moveCam(corner) {
if (camId < 0 || baseWidth <= 0 || camW <= 0 || camH <= 0) return;
@@ -109,6 +116,7 @@ Singleton {
recording = false; paused = false; duration = 0;
stateFromEvents = false;
scenes = []; scene = ""; camId = -1; camOn = false;
+ sources = [];
camW = 0; camH = 0;
desktopAudio = ""; desktopMuted = false;
baseWidth = 0; baseHeight = 0;
@@ -238,6 +246,7 @@ Singleton {
request("GetSceneItemList", { sceneName: scene });
break;
case "GetSceneItemList": {
+ sources = r.sceneItems.map(i => ({ name: i.sourceName, kind: i.inputKind }));
const it = r.sceneItems.find(i => i.inputKind === "v4l2_input");
camId = it ? it.sceneItemId : -1;
camOn = !!it && it.sceneItemEnabled;
diff --git a/desktop/island/ObsPill.qml b/desktop/island/ObsPill.qml
index 6ae9b4e..3fdb4a3 100644
--- a/desktop/island/ObsPill.qml
+++ b/desktop/island/ObsPill.qml
@@ -27,6 +27,12 @@ Capsule {
panelWidth: 260
panelHeight: controls.implicitHeight + 28
+ // A scene whose only source is a PipeWire capture is the window scene.
+ // ponytail: a window scene with more than one source needs a per-scene
+ // designation instead of this count.
+ readonly property bool windowOnly: Obs.sources.length === 1
+ && Obs.sources[0].kind === "pipewire-screen-capture-source"
+
Row {
id: rest
anchors.centerIn: parent
@@ -93,7 +99,7 @@ Capsule {
Row {
spacing: 8
- visible: Obs.camId >= 0 || Obs.desktopAudio !== ""
+ visible: Obs.camId >= 0 || Obs.desktopAudio !== "" || pill.windowOnly
Button {
visible: Obs.camId >= 0
icon: Obs.camOn ? "\udb81\udd67" : "\udb81\udd68"
@@ -106,6 +112,13 @@ Capsule {
text: "Audio"
onClicked: Obs.toggleAudio()
}
+ // OBS's source dialog, where the Wayland portal window picker runs.
+ Button {
+ visible: pill.windowOnly
+ icon: "\uf2d0"
+ text: "Window"
+ onClicked: Obs.openSource(Obs.sources[0].name)
+ }
}
// The webcam's four corners on the recorded canvas.
diff --git a/desktop/island/README.md b/desktop/island/README.md
index 71455f3..7bd7b10 100644
--- a/desktop/island/README.md
+++ b/desktop/island/README.md
@@ -84,11 +84,13 @@ click opens its panel in the capsule: Record or Stop, Pause or Resume
(while recording), Webcam (the first `v4l2_input` item in the current
scene; absent without one), Audio (mute the global "Desktop Audio" input),
four corner buttons that move the webcam on the canvas, and a scene grid,
-four columns of icon tiles, current one highlighted, click to switch. The
-scene glyphs come from `~/.config/quickshell/obs-scene-icons.json`, watched
-and edited from the settings window's "OBS scenes" page; an unmapped scene
-shows `?`. While recording the sliver pulses red, and holds dim while
-paused.
+four columns of icon tiles, current one highlighted, click to switch. In a
+scene whose only source is a PipeWire capture (the window scene), a Window
+button opens that source's properties, where OBS's portal picker chooses the
+window. The scene glyphs come from
+`~/.config/quickshell/obs-scene-icons.json`, watched and edited from the
+settings window's "OBS scenes" page; an unmapped scene shows `?`. While
+recording the sliver pulses red, and holds dim while paused.
QML's `WebSocket` does not expose the close code, so a wrong password
reads the same as OBS quitting; it is logged once as "closed before