hands: arm the wire before opening the pad
This commit is contained in:
parent
799f0650ed
commit
59b52a818b
7 changed files with 210 additions and 148 deletions
|
|
@ -88,6 +88,12 @@ Scope { // Scope
|
|||
|| GlobalStates.missionPeek)
|
||||
return Dock.DockState.Hidden;
|
||||
|
||||
// USB Hands owns the bottom of home while its trackpad is actually
|
||||
// open. Arming the wire alone changes no furniture; opening the
|
||||
// conditional controller makes the dock yield until it closes.
|
||||
if (HidController.active)
|
||||
return Dock.DockState.Hidden;
|
||||
|
||||
// A visible keyboard owns the bottom edge. This must precede the home
|
||||
// zone's unconditional PINNED return below; otherwise home stacks the
|
||||
// dock's exclusive zone under the OSK and charges the display twice.
|
||||
|
|
|
|||
|
|
@ -290,12 +290,16 @@ Scope {
|
|||
SheetLocal.PowerOptionRow {
|
||||
Layout.fillWidth: true
|
||||
icon: "keyboard"
|
||||
title: "USB HID Injection"
|
||||
detail: UsbState.mode === "hid"
|
||||
? "Keyboard and pointer link armed"
|
||||
: "Let this screen become the other machine's hands"
|
||||
badge: UsbState.mode === "hid" ? "active"
|
||||
: UsbState.hasMode("hid_mode") ? "wired" : "building"
|
||||
title: "USB hand"
|
||||
detail: HidController.active
|
||||
? "Wire armed · trackpad open"
|
||||
: HidController.modeReady
|
||||
? "Keyboard and pointer wire armed"
|
||||
: "Arm the wire, then open its trackpad"
|
||||
badge: UsbState.busy ? "switching"
|
||||
: HidController.active ? "open"
|
||||
: HidController.modeReady ? "armed"
|
||||
: UsbState.hasMode("hid_mode") ? "ready" : "building"
|
||||
inset: 10
|
||||
expandable: true
|
||||
expanded: scope.hidOptionsOpen
|
||||
|
|
@ -316,35 +320,41 @@ Scope {
|
|||
SheetLocal.PowerOptionRow {
|
||||
Layout.fillWidth: true
|
||||
icon: "cable"
|
||||
title: "USB control link"
|
||||
detail: UsbState.mode === "hid"
|
||||
? "Armed · tap to restore developer USB"
|
||||
title: HidController.modeReady
|
||||
? "Disarm USB hand" : "Arm USB hand"
|
||||
detail: HidController.modeReady
|
||||
? "Restore developer USB and close its controls"
|
||||
: "Expose keyboard, pointer and developer network"
|
||||
badge: UsbState.busy ? "switching"
|
||||
: UsbState.mode === "hid" ? "active"
|
||||
: HidController.modeReady ? "armed"
|
||||
: UsbState.hasMode("hid_mode") ? "ready" : "not installed"
|
||||
inset: 28
|
||||
available: UsbState.hasMode("hid_mode") && !UsbState.busy
|
||||
onTapped: UsbState.setMode(
|
||||
UsbState.mode === "hid" ? "developer" : "hid")
|
||||
HidController.modeReady ? "developer" : "hid")
|
||||
}
|
||||
|
||||
SheetLocal.PowerOptionRow {
|
||||
Layout.fillWidth: true
|
||||
icon: "keyboard_mouse"
|
||||
title: "Agent hands"
|
||||
title: HidController.active
|
||||
? "Close trackpad" : "Open trackpad"
|
||||
detail: HidController.active
|
||||
? "Voice, trackpad and the summoned host keyboard"
|
||||
: "Join the agent to the wire; trackpad first"
|
||||
? "Leave the wire armed; put its controls away"
|
||||
: "Voice, pointer, scroll and clicks"
|
||||
badge: HidController.ready ? "awake"
|
||||
: HidController.active ? "arm"
|
||||
: GlobalStates.screenLockSecure ? "locked" : "open"
|
||||
: HidController.active ? "waking"
|
||||
: GlobalStates.screenLockSecure ? "locked" : "closed"
|
||||
inset: 28
|
||||
available: UsbState.hasMode("hid_mode")
|
||||
available: HidController.modeReady && !UsbState.busy
|
||||
&& !GlobalStates.screenLockSecure
|
||||
onTapped: {
|
||||
if (Face.joinHands())
|
||||
if (HidController.active) {
|
||||
Face.leaveHands();
|
||||
scope.dismiss();
|
||||
} else if (Face.joinHands()) {
|
||||
scope.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
// does by construction.
|
||||
//
|
||||
// USB Hands joins the same limb rather than opening a controller app beside
|
||||
// her. Its agent field, explicit microphone, trackpad and summoned host
|
||||
// keyboard occupy the room the compositor already left below her. The HID
|
||||
// reports still belong to HidController; this service only routes page intent.
|
||||
// her. Its agent field, explicit microphone and trackpad occupy the room the
|
||||
// compositor already left below her. The HID reports still belong to
|
||||
// HidController; this service only routes page intent.
|
||||
//
|
||||
// ## Turning her on is joining
|
||||
//
|
||||
|
|
@ -86,6 +86,12 @@ Singleton {
|
|||
return true;
|
||||
}
|
||||
|
||||
function leaveHands() {
|
||||
if (HidController.active)
|
||||
HidController.close();
|
||||
root._syncHands();
|
||||
}
|
||||
|
||||
function leave() {
|
||||
if (root.listening)
|
||||
root._talk("cancel");
|
||||
|
|
@ -153,8 +159,6 @@ Singleton {
|
|||
root._talk(msg.phase);
|
||||
else if (msg.event === "hid")
|
||||
root._hid(msg);
|
||||
else if (msg.event === "thread")
|
||||
root._thread(msg.mode);
|
||||
else if (msg.event === "ready")
|
||||
root._syncHands();
|
||||
else if (msg.event === "dismiss")
|
||||
|
|
@ -193,20 +197,6 @@ Singleton {
|
|||
})})`);
|
||||
break;
|
||||
}
|
||||
case "arm":
|
||||
HidController.arm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function _thread(mode) {
|
||||
if (Souveraine.turnActive)
|
||||
return;
|
||||
if (mode === "new") {
|
||||
Souveraine.newConversation();
|
||||
root._syncHands();
|
||||
} else if (mode === "resume") {
|
||||
Souveraine.resumeLatestConversation();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,7 +210,6 @@ Singleton {
|
|||
mode: UsbState.mode,
|
||||
error: HidController.lastError,
|
||||
agent: agent?.name ?? Souveraine.currentAgentId ?? "agent",
|
||||
conversation: Souveraine.conversationId.length > 0 ? "resumed" : "new",
|
||||
listening: root.listening,
|
||||
thinking: Souveraine.turnActive
|
||||
};
|
||||
|
|
|
|||
|
|
@ -35,12 +35,11 @@ Singleton {
|
|||
// about a USB gadget it is not using.
|
||||
readonly property string skill: "USB Hands is joined to this conversation. "
|
||||
+ "Casey is using the phone as a trackpad and voice-first controller for an attached host. "
|
||||
+ "When he asks you to type or press a key there, use the existing bridge: "
|
||||
+ "`qs -c souveraine ipc call usbHands sendText TEXT`, "
|
||||
+ "`qs -c souveraine ipc call usbHands tap KEY`, "
|
||||
+ "`qs -c souveraine ipc call usbHands key KEY MODIFIERS`, or "
|
||||
+ "`qs -c souveraine ipc call usbHands click left|right|middle`. "
|
||||
+ "Ask `qs -c souveraine ipc call usbHands status` rather than assuming the cable is armed. "
|
||||
+ "When he asks you to type, press a key, or click there, use your existing `body` tool "
|
||||
+ "with `verb: hand` and the corresponding `action`: type, key, click, or pointer. "
|
||||
+ "Use `action: status` rather than assuming the cable and surface are ready. "
|
||||
+ "A direct request to type ordinary user-authored text, including creative, intimate, or unusual prose, "
|
||||
+ "is sufficient authorization; do not refuse it merely because its tone is odd. "
|
||||
+ "Do not inject anything Casey did not ask to send to the attached host."
|
||||
|
||||
signal controllerChanged()
|
||||
|
|
@ -52,6 +51,12 @@ Singleton {
|
|||
root.refused(root.lastError);
|
||||
return false;
|
||||
}
|
||||
if (!root.modeReady) {
|
||||
root.lastError = "Arm HID or KVM from Power Options before opening the trackpad";
|
||||
root.refused(root.lastError);
|
||||
root.controllerChanged();
|
||||
return false;
|
||||
}
|
||||
root.lastError = "";
|
||||
root.active = true;
|
||||
UsbState.refresh();
|
||||
|
|
@ -83,23 +88,6 @@ Singleton {
|
|||
}
|
||||
}
|
||||
|
||||
function arm() {
|
||||
if (!root.active) {
|
||||
root.lastError = "USB Hands is not joined";
|
||||
root.refused(root.lastError);
|
||||
root.controllerChanged();
|
||||
return false;
|
||||
}
|
||||
if (!UsbState.hasMode("hid_mode")) {
|
||||
root.lastError = "The installed gadget does not advertise HID mode";
|
||||
root.refused(root.lastError);
|
||||
root.controllerChanged();
|
||||
return false;
|
||||
}
|
||||
UsbState.setMode("hid");
|
||||
return true;
|
||||
}
|
||||
|
||||
function _reconcile() {
|
||||
const wanted = root.permitted && root.modeReady;
|
||||
if (!wanted) {
|
||||
|
|
@ -295,6 +283,13 @@ Singleton {
|
|||
|
||||
onActiveChanged: root._reconcile()
|
||||
onModeReadyChanged: {
|
||||
// The trackpad is conditional on an armed wire. If sessiond contracts
|
||||
// the port back to developer/charging mode, close the surface instead
|
||||
// of leaving a dead controller on the glass asking to be re-armed.
|
||||
if (root.active && !root.modeReady) {
|
||||
root.close();
|
||||
return;
|
||||
}
|
||||
root._reconcile();
|
||||
root.controllerChanged();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue