diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-04 15:31:14 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-04 16:51:10 +0300 |
| commit | 15cab964f3494b77159caaea289e17e1596e0720 (patch) | |
| tree | d9614056c26b0d148771a464fc2eb0f0cabc60a2 /src/api | |
| parent | b78a8a5c565e66e7e5ba9a06d9cb7f3a771fc4b0 (diff) | |
feat: emit layout update events for runtime layout changes
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/schema/events.rs | 15 | ||||
| -rw-r--r-- | src/api/schema/tests.rs | 35 | ||||
| -rw-r--r-- | src/api/subscriptions.rs | 4 |
3 files changed, 50 insertions, 4 deletions
diff --git a/src/api/schema/events.rs b/src/api/schema/events.rs index 2fbce4d0..aff3d2a2 100644 --- a/src/api/schema/events.rs +++ b/src/api/schema/events.rs @@ -72,6 +72,8 @@ pub enum Subscription { #[serde(default, skip_serializing_if = "Option::is_none")] agent_status: Option<AgentStatus>, }, + #[serde(rename = "layout.updated")] + LayoutUpdated {}, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] @@ -204,6 +206,7 @@ pub enum EventKind { PaneExited, PaneAgentDetected, PaneAgentStatusChanged, + LayoutUpdated, } impl EventKind { @@ -231,6 +234,7 @@ impl EventKind { EventKind::PaneExited => "pane.exited", EventKind::PaneAgentDetected => "pane.agent_detected", EventKind::PaneAgentStatusChanged => "pane.agent_status_changed", + EventKind::LayoutUpdated => "layout.updated", } } } @@ -259,6 +263,7 @@ pub const KNOWN_EVENT_KINDS: &[EventKind] = &[ EventKind::PaneExited, EventKind::PaneAgentDetected, EventKind::PaneAgentStatusChanged, + EventKind::LayoutUpdated, ]; pub const PLUGIN_HOOK_EVENT_KINDS: &[EventKind] = &[ @@ -325,14 +330,15 @@ mod known_event_name_tests { } #[test] - fn plugin_hook_event_names_exclude_unemitted_output_change() { + fn plugin_hook_event_names_exclude_high_volume_events() { let names = plugin_hook_event_names(); assert!(!names.contains(&"pane.output_changed")); + assert!(!names.contains(&"layout.updated")); assert!(names.contains(&"pane.moved")); } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)] pub struct EventEnvelope { pub event: EventKind, pub data: EventData, @@ -383,7 +389,7 @@ pub struct PaneAgentStatusChangedEvent { pub state_labels: HashMap<String, String>, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(tag = "type", rename_all = "snake_case")] pub enum EventData { WorkspaceCreated { @@ -502,4 +508,7 @@ pub enum EventData { #[serde(default, skip_serializing_if = "HashMap::is_empty")] state_labels: HashMap<String, String>, }, + LayoutUpdated { + layout: super::panes::PaneLayoutSnapshot, + }, } diff --git a/src/api/schema/tests.rs b/src/api/schema/tests.rs index 5106fafe..abd96656 100644 --- a/src/api/schema/tests.rs +++ b/src/api/schema/tests.rs @@ -374,6 +374,34 @@ fn event_envelope_round_trips() { tabs: vec![], }, }, + EventEnvelope { + event: EventKind::LayoutUpdated, + data: EventData::LayoutUpdated { + layout: PaneLayoutSnapshot { + workspace_id: "w_1".into(), + tab_id: "w_1:1".into(), + zoomed: false, + area: PaneLayoutRect { + x: 0, + y: 0, + width: 100, + height: 24, + }, + focused_pane_id: "w_1-1".into(), + panes: vec![PaneLayoutPane { + pane_id: "w_1-1".into(), + focused: true, + rect: PaneLayoutRect { + x: 0, + y: 0, + width: 100, + height: 24, + }, + }], + splits: vec![], + }, + }, + }, ]; for event in events { @@ -934,12 +962,17 @@ fn authority_mutation_requests_round_trip() { let subscription = Request { id: "sub_moves".into(), method: Method::EventsSubscribe(EventsSubscribeParams { - subscriptions: vec![Subscription::WorkspaceMoved {}, Subscription::TabMoved {}], + subscriptions: vec![ + Subscription::WorkspaceMoved {}, + Subscription::TabMoved {}, + Subscription::LayoutUpdated {}, + ], }), }; let json = serde_json::to_string(&subscription).unwrap(); assert!(json.contains("\"type\":\"workspace.moved\"")); assert!(json.contains("\"type\":\"tab.moved\"")); + assert!(json.contains("\"type\":\"layout.updated\"")); let restored: Request = serde_json::from_str(&json).unwrap(); assert_eq!(restored, subscription); } diff --git a/src/api/subscriptions.rs b/src/api/subscriptions.rs index f3b82090..73586b99 100644 --- a/src/api/subscriptions.rs +++ b/src/api/subscriptions.rs @@ -188,6 +188,10 @@ impl ActiveSubscription { event_kind: crate::api::schema::EventKind::PaneAgentDetected, last_sequence: 0, })), + Subscription::LayoutUpdated {} => Ok(Self::Event(ActiveEventSubscription { + event_kind: crate::api::schema::EventKind::LayoutUpdated, + last_sequence: 0, + })), Subscription::PaneOutputMatched { pane_id, source, |
