Skip to content

Commit 27bfb28

Browse files
committed
refactor: rename window_state to window and add Window struct
- Rename window_state.rs to window.rs - Add Window struct that holds both WindowHandle<RootView> and WindowState - Update global_state to use Window instead of WindowState directly - Update all references in lib.rs, renderer.rs, host_command.rs
1 parent f096d6e commit 27bfb28

7 files changed

Lines changed: 344 additions & 48 deletions

File tree

multi-agent-research-system.md

Lines changed: 245 additions & 0 deletions
Large diffs are not rendered by default.

rust/src/AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ rust/src/
1616
├── renderer.rs # RootView, render_element_to_gpui (div/text/span/img)
1717
├── element.rs # ReactElement, ElementStyle, ElementData structures
1818
├── host_command.rs # async_channel command bus (TriggerRender, UpdateElements)
19-
├── window_state.rs # ElementTree, render_count, ROOT_ELEMENT_ID
19+
├── window.rs # Window, WindowState, element tree management
2020
├── global_state.rs # Global state management (lazy_static)
2121
├── ffi_types.rs # FFI type bindings (serde)
2222
└── logging.rs # Logging utilities (logforth)
@@ -30,7 +30,7 @@ rust/src/
3030
| FFI helpers | ffi_helpers.rs | ptr_to_u64, read_c_string, validate_result_ptr |
3131
| GPUI rendering | renderer.rs | render_element_to_gpui (div/text/span/img) |
3232
| Command bus | host_command.rs | init(cx), send_host_command(TriggerRender) |
33-
| Window state | window_state.rs | update_element_tree(), render_count, ROOT_ELEMENT_ID |
33+
| Window | window.rs | Window, WindowState, update_element_tree(), render_count |
3434
| Element structures | element.rs | ReactElement, ElementStyle, ChildElement |
3535

3636
## CONVENTIONS

rust/src/global_state.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use std::{collections::HashMap, sync::{Arc, RwLock, atomic::{AtomicBool, Ordering}}};
22

3-
use gpui::Global;
4-
5-
use crate::window_state::WindowState;
3+
use gpui::{AnyWindowHandle, Global, WindowHandle};
4+
use crate::renderer::RootView;
5+
use crate::window::Window;
66

77
pub struct GlobalState {
88
gpui_initialized: AtomicBool,
99
gpui_thread_started: AtomicBool,
10-
window_states: RwLock<HashMap<u64, Arc<WindowState>>>,
10+
windows: RwLock<HashMap<u64, Arc<Window>>>,
1111
}
1212

1313
impl Global for GlobalState {}
@@ -17,7 +17,7 @@ impl GlobalState {
1717
Self {
1818
gpui_initialized: AtomicBool::new(false),
1919
gpui_thread_started: AtomicBool::new(false),
20-
window_states: RwLock::new(HashMap::new()),
20+
windows: RwLock::new(HashMap::new()),
2121
}
2222
}
2323

@@ -33,21 +33,27 @@ impl GlobalState {
3333
self.gpui_thread_started.store(value, Ordering::SeqCst);
3434
}
3535

36-
pub fn get_window_state(&self, window_id: u64) -> Arc<WindowState> {
37-
let mut states =
38-
self.window_states.write().expect("Failed to acquire window_states write lock");
39-
states.entry(window_id).or_insert_with(|| Arc::new(WindowState::new())).clone()
36+
/// Add a window with its GPUI handle
37+
pub fn add_window(&self, handle: WindowHandle<RootView>) {
38+
let window_id = handle.window_id().as_u64();
39+
let mut windows = self.windows.write().expect("Failed to acquire windows write lock");
40+
windows.insert(window_id, Arc::new(Window::new(handle)));
41+
}
42+
43+
/// Get a window by ID, returns None if not found
44+
pub fn get_window(&self, window_id: u64) -> Option<Arc<Window>> {
45+
let windows = self.windows.read().expect("Failed to acquire windows read lock");
46+
windows.get(&window_id).cloned()
4047
}
4148

42-
pub fn get_window_state_ref(&self, window_id: u64) -> Option<Arc<WindowState>> {
43-
let states = self.window_states.read().expect("Failed to acquire window_states read lock");
44-
states.get(&window_id).cloned()
49+
pub fn get_window_ref(&self, window_id: u64) -> Option<Arc<Window>> {
50+
let windows = self.windows.read().expect("Failed to acquire windows read lock");
51+
windows.get(&window_id).cloned()
4552
}
4653

47-
pub fn remove_window_state(&self, window_id: u64) {
48-
let mut states =
49-
self.window_states.write().expect("Failed to acquire window_states write lock");
50-
states.remove(&window_id);
54+
pub fn remove_window(&self, window_id: u64) {
55+
let mut windows = self.windows.write().expect("Failed to acquire windows write lock");
56+
windows.remove(&window_id);
5157
}
5258
}
5359

rust/src/host_command.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -116,28 +116,29 @@ pub fn handle_on_app_thread(command: HostCommand, app: &mut App) {
116116
let window = app.open_window(window_options, |_window, cx| {
117117
let state = cx.new(|_| crate::renderer::RootState { render_count: 0 });
118118
cx.new(|_| crate::renderer::RootView { state, last_render: 0, window_id: 0 })
119-
});
120-
let real_window_id = window.as_ref().unwrap().window_id().as_u64();
119+
}).unwrap();
120+
let window_id = window.window_id().as_u64();
121+
log::info!("Created window with id: {}", window_id);
121122

122-
log::info!("Created window with id: {}", real_window_id);
123-
124-
let handle = window.as_ref().unwrap();
125-
handle
123+
window
126124
.update(app, |view: &mut crate::renderer::RootView, _, _| {
127-
view.window_id = real_window_id;
125+
view.window_id = window_id;
128126
})
129127
.ok();
128+
// Store the window handle in our Window struct
129+
GLOBAL_STATE.add_window(window);
130130

131-
let _ = GLOBAL_STATE.get_window_state(real_window_id);
132-
133-
let _ = response_tx.send(real_window_id);
131+
let _ = response_tx.send(window_id);
134132
}
135133
HostCommand::TriggerRender { window_id } => {
136-
if let Some(window) = app.windows().iter().find(|w| w.window_id() == window_id.into()) {
137-
let window_state = GLOBAL_STATE.get_window_state(window_id);
138-
window_state.increment_render_count();
139-
140-
if let Err(e) = window.update(app, |_, window, _cx| {
134+
if let Some(gpui_window) = app.windows().iter().find(|w| w.window_id() == window_id.into()) {
135+
let Some(window) = GLOBAL_STATE.get_window(window_id) else {
136+
log::warn!("TriggerRender: window {} not found", window_id);
137+
return;
138+
};
139+
window.state().increment_render_count();
140+
141+
if let Err(e) = gpui_window.update(app, |_, window, _cx| {
141142
log::trace!("Calling window.refresh() for window {}", window_id);
142143
window.refresh();
143144
}) {

rust/src/lib.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod global_state;
55
mod host_command;
66
mod logging;
77
mod renderer;
8-
mod window_state;
8+
mod window;
99

1010
use std::{ffi::{CStr, c_char}, sync::Arc};
1111

@@ -115,7 +115,10 @@ pub extern "C" fn gpui_render_frame(
115115
children
116116
);
117117

118-
let window_state = GLOBAL_STATE.get_window_state(window_id);
118+
let Some(window) = GLOBAL_STATE.get_window(window_id) else {
119+
log::error!("gpui_render_frame: window {} not found", window_id);
120+
return;
121+
};
119122

120123
let element = Arc::new(ReactElement {
121124
global_id,
@@ -126,7 +129,8 @@ pub extern "C" fn gpui_render_frame(
126129
event_handlers: None,
127130
});
128131

129-
let mut element_map = window_state
132+
let mut element_map = window
133+
.state()
130134
.element_map
131135
.lock()
132136
.expect("Failed to acquire element_map lock in gpui_render_frame");
@@ -148,11 +152,11 @@ pub extern "C" fn gpui_render_frame(
148152

149153
drop(element_map);
150154

151-
window_state.set_root_element_id(global_id);
155+
window.state().set_root_element_id(global_id);
152156

153-
window_state.rebuild_tree(global_id, &children);
157+
window.state().rebuild_tree(global_id, &children);
154158

155-
window_state.update_element_tree();
159+
window.state().update_element_tree();
156160

157161
send_host_command(HostCommand::TriggerRender { window_id });
158162

@@ -166,8 +170,11 @@ pub extern "C" fn gpui_render_frame(
166170
pub extern "C" fn gpui_trigger_render(window_id_ptr: *const u8, _result: *mut FfiResult) {
167171
unsafe {
168172
let window_id = ptr_to_u64(window_id_ptr);
169-
let window_state = GLOBAL_STATE.get_window_state(window_id);
170-
window_state.increment_render_count();
173+
let Some(window) = GLOBAL_STATE.get_window(window_id) else {
174+
log::error!("gpui_render_frame: window {} not found", window_id);
175+
return;
176+
};
177+
window.state().increment_render_count();
171178
send_host_command(HostCommand::TriggerRender { window_id });
172179
}
173180
}
@@ -197,9 +204,13 @@ pub extern "C" fn gpui_batch_update_elements(
197204

198205
log::info!("Batch update: Processing {} elements for window {}", count, window_id);
199206

200-
let window_state = GLOBAL_STATE.get_window_state(window_id);
207+
let Some(window) = GLOBAL_STATE.get_window(window_id) else {
208+
log::error!("gpui_render_frame: window {} not found", window_id);
209+
return;
210+
};
201211

202-
let mut element_map = window_state
212+
let mut element_map = window
213+
.state()
203214
.element_map
204215
.lock()
205216
.expect("Failed to acquire element_map lock in gpui_batch_update_elements");
@@ -258,7 +269,7 @@ pub extern "C" fn gpui_batch_update_elements(
258269
// window_state.update_element_tree();
259270
send_host_command(HostCommand::TriggerRender { window_id });
260271

261-
let trigger = window_state.get_render_count();
272+
let trigger = window.state().get_render_count();
262273
log::debug!("Triggering render, current count: {}", trigger);
263274

264275
*result = FfiResult::success();

rust/src/renderer.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ pub struct RootView {
1414

1515
impl RootView {
1616
fn update_state(&mut self, cx: &mut Context<Self>) {
17-
let window_state = GLOBAL_STATE.get_window_state(self.window_id);
18-
let trigger = window_state.get_render_count();
17+
let Some(window) = GLOBAL_STATE.get_window(self.window_id) else {
18+
log::warn!("update_state: window {} not found", self.window_id);
19+
return;
20+
};
21+
let trigger = window.state().get_render_count();
1922
log::trace!(
2023
"update_state: window_id={}, trigger={}, last_render={}",
2124
self.window_id,
@@ -42,8 +45,12 @@ impl Render for RootView {
4245
let render_start = std::time::Instant::now();
4346
self.update_state(cx);
4447

45-
let window_state = GLOBAL_STATE.get_window_state(self.window_id);
46-
let tree = window_state
48+
let Some(window) = GLOBAL_STATE.get_window(self.window_id) else {
49+
log::warn!("RootView.render: window {} not found", self.window_id);
50+
return div().child("Window not found");
51+
};
52+
let tree = window
53+
.state()
4754
.element_tree
4855
.lock()
4956
.expect("Failed to acquire element_tree lock in RootView.render");
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::{collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicU64, Ordering}}};
22

3+
use gpui::WindowHandle;
4+
35
use crate::element::ReactElement;
6+
use crate::renderer::RootView;
47

58
pub struct WindowState {
69
pub root_element_id: AtomicU64,
@@ -89,3 +92,26 @@ impl WindowState {
8992
impl Default for WindowState {
9093
fn default() -> Self { Self::new() }
9194
}
95+
96+
pub struct Window {
97+
/// The GPUI window handle
98+
gpui_window: WindowHandle<RootView>,
99+
/// The React element state for this window
100+
state: Arc<WindowState>,
101+
}
102+
103+
impl Window {
104+
/// Create a new window with the given GPUI handle
105+
pub fn new(gpui_window: WindowHandle<RootView>) -> Self {
106+
Self { gpui_window, state: Arc::new(WindowState::new()) }
107+
}
108+
109+
/// Get a reference to the GPUI window handle
110+
pub fn gpui_window(&self) -> &WindowHandle<RootView> { &self.gpui_window }
111+
112+
/// Get the window state
113+
pub fn state(&self) -> &Arc<WindowState> { &self.state }
114+
115+
/// Get mutable access to the window state
116+
pub fn state_mut(&mut self) -> &mut Arc<WindowState> { &mut self.state }
117+
}

0 commit comments

Comments
 (0)