1use crate::connection::Connection;
4use crate::error::{Error, Result};
5use crate::proto;
6use crate::request;
7use crate::validate;
8use std::sync::Arc;
9use tokio::io::{AsyncRead, AsyncWrite};
10
11pub struct Window<S> {
13 pub id: String,
15 conn: Arc<Connection<S>>,
16}
17
18impl<S: AsyncRead + AsyncWrite + Unpin + Send + 'static> Window<S> {
19 pub fn new(id: String, conn: Arc<Connection<S>>) -> Result<Self> {
21 validate::identifier(&id, "window")?;
22 Ok(Self { id, conn })
23 }
24
25 pub(crate) fn new_unchecked(id: String, conn: Arc<Connection<S>>) -> Self {
26 Self { id, conn }
27 }
28
29 pub async fn create_tab(&self, profile_name: Option<&str>) -> Result<CreateTabResult> {
31 let resp = self
32 .conn
33 .call(request::create_tab(profile_name, Some(&self.id)))
34 .await?;
35 match resp.submessage {
36 Some(proto::server_originated_message::Submessage::CreateTabResponse(r)) => {
37 check_status_i32(r.status, "CreateTab")?;
38 Ok(CreateTabResult {
39 tab_id: r.tab_id.map(|id| id.to_string()),
40 session_id: r.session_id,
41 window_id: r.window_id,
42 })
43 }
44 _ => Err(Error::UnexpectedResponse {
45 expected: "CreateTabResponse",
46 }),
47 }
48 }
49
50 pub async fn activate(&self) -> Result<()> {
52 let resp = self.conn.call(request::activate_window(&self.id)).await?;
53 match resp.submessage {
54 Some(proto::server_originated_message::Submessage::ActivateResponse(r)) => {
55 check_status_i32(r.status, "Activate")
56 }
57 _ => Err(Error::UnexpectedResponse {
58 expected: "ActivateResponse",
59 }),
60 }
61 }
62
63 pub async fn close(&self, force: bool) -> Result<()> {
65 let resp = self
66 .conn
67 .call(request::close_windows(vec![self.id.clone()], force))
68 .await?;
69 match resp.submessage {
70 Some(proto::server_originated_message::Submessage::CloseResponse(_)) => Ok(()),
71 _ => Err(Error::UnexpectedResponse {
72 expected: "CloseResponse",
73 }),
74 }
75 }
76
77 pub async fn get_property(&self, name: &str) -> Result<Option<String>> {
79 let resp = self
80 .conn
81 .call(request::get_property_window(&self.id, name))
82 .await?;
83 match resp.submessage {
84 Some(proto::server_originated_message::Submessage::GetPropertyResponse(r)) => {
85 check_status_i32(r.status, "GetProperty")?;
86 Ok(r.json_value)
87 }
88 _ => Err(Error::UnexpectedResponse {
89 expected: "GetPropertyResponse",
90 }),
91 }
92 }
93
94 pub async fn set_property(&self, name: &str, json_value: &str) -> Result<()> {
96 validate::json_value(json_value)?;
97 let resp = self
98 .conn
99 .call(request::set_property_window(&self.id, name, json_value))
100 .await?;
101 match resp.submessage {
102 Some(proto::server_originated_message::Submessage::SetPropertyResponse(r)) => {
103 check_status_i32(r.status, "SetProperty")
104 }
105 _ => Err(Error::UnexpectedResponse {
106 expected: "SetPropertyResponse",
107 }),
108 }
109 }
110
111 pub async fn get_variable(&self, name: &str) -> Result<Option<String>> {
113 let resp = self
114 .conn
115 .call(request::get_variable_window(
116 &self.id,
117 vec![name.to_string()],
118 ))
119 .await?;
120 match resp.submessage {
121 Some(proto::server_originated_message::Submessage::VariableResponse(r)) => {
122 check_status_i32(r.status, "Variable")?;
123 Ok(r.values.into_iter().next())
124 }
125 _ => Err(Error::UnexpectedResponse {
126 expected: "VariableResponse",
127 }),
128 }
129 }
130
131 pub fn connection(&self) -> &Connection<S> {
133 &self.conn
134 }
135}
136
137pub struct CreateTabResult {
139 pub tab_id: Option<String>,
140 pub session_id: Option<String>,
141 pub window_id: Option<String>,
142}
143
144fn check_status_i32(status: Option<i32>, op: &str) -> Result<()> {
145 match status {
146 Some(0) | None => Ok(()),
147 Some(code) => Err(Error::Status(format!("{op} returned status {code}"))),
148 }
149}