libobs_wrapper\display\window_manager/
position_trait.rs1#[cfg(windows)]
2use windows::Win32::{
3 Foundation::HWND,
4 Graphics::Gdi::{RedrawWindow, RDW_ERASE, RDW_INVALIDATE},
5 UI::WindowsAndMessaging::{
6 SetWindowPos, HWND_BOTTOM, SWP_NOACTIVATE, SWP_NOCOPYBITS, SWP_NOSIZE, SWP_NOZORDER,
7 SWP_SHOWWINDOW,
8 },
9};
10
11use crate::display::window_manager::WindowPositionTrait;
12use crate::display::DISPLAY_POSITIONS;
13use crate::utils::ObsError;
14use crate::{display::ObsDisplayRef, run_with_obs};
15
16impl WindowPositionTrait for ObsDisplayRef {
17 fn set_render_at_bottom(&self, _render_at_bottom: bool) -> Result<(), ObsError> {
18 log::trace!("Set render bottom");
19 #[cfg(windows)]
20 if let Some(m) = self.child_window_handler.as_ref() {
21 let mut m = m
22 .write()
23 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
24
25 m.render_at_bottom = _render_at_bottom;
26 }
27 Ok(())
28 }
29
30 fn get_render_at_bottom(&self) -> Result<bool, ObsError> {
31 #[cfg(windows)]
32 if let Some(m) = self.child_window_handler.as_ref() {
33 let m = m
34 .read()
35 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
36 return Ok(m.render_at_bottom);
37 }
38
39 Ok(false)
40 }
41
42 fn set_pos(&self, x: i32, y: i32) -> Result<(), ObsError> {
43 log::trace!("Set pos {x} {y}");
44
45 #[cfg(windows)]
46 if let Some(m) = self.child_window_handler.as_ref() {
47 let mut m = m
48 .write()
49 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
50
51 assert!(
52 m.obs_display.is_some(),
53 "Invalid state. The display should have been created and set, but it wasn't."
54 );
55
56 let insert_after = if m.render_at_bottom {
57 HWND_BOTTOM
58 } else {
59 HWND::default()
60 };
61
62 m.x = x;
63 m.y = y;
64
65 unsafe {
66 let flags = SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE;
67 SetWindowPos(
69 m.window_handle.get_hwnd(),
70 Some(insert_after),
71 x,
72 y,
73 1_i32,
74 1_i32,
75 flags,
76 )
77 .map_err(|e| ObsError::DisplayCreationError(format!("{:?}", e)))?;
78 }
79
80 drop(m); self.update_color_space()?;
83 return Ok(());
84 }
85
86 *DISPLAY_POSITIONS
87 .write()
88 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?
89 .get_mut(&self.id)
90 .ok_or_else(|| ObsError::LockError("Position not found".to_string()))? = (x, y);
91
92 self.update_color_space()?;
93 Ok(())
94 }
95
96 fn set_size(&self, width: u32, height: u32) -> Result<(), ObsError> {
97 log::trace!("Set size {width} {height}");
98
99 #[cfg(windows)]
100 if let Some(m) = self.child_window_handler.as_ref() {
101 let mut m = m
102 .write()
103 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
104
105 assert!(
106 m.obs_display.is_some(),
107 "Invalid state. The display should have been created and set, but it wasn't."
108 );
109
110 m.width = width;
111 m.height = height;
112
113 unsafe {
114 SetWindowPos(
115 m.window_handle.get_hwnd(),
116 None,
117 m.x,
118 m.y,
119 width as i32,
120 height as i32,
121 SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW,
122 )
123 .map_err(|e| ObsError::DisplayCreationError(format!("{:?}", e)))?;
124
125 let _ = RedrawWindow(
126 Some(m.window_handle.get_hwnd()),
127 None,
128 None,
129 RDW_ERASE | RDW_INVALIDATE,
130 );
131 }
132 }
133
134 let pointer = self.display.clone();
135 run_with_obs!(self.runtime, (pointer), move || unsafe {
136 libobs::obs_display_resize(pointer, width, height);
137 libobs::obs_display_update_color_space(pointer);
139 })
140 .map_err(|e| ObsError::InvocationError(format!("{:?}", e)))?;
141 Ok(())
142 }
143
144 fn get_pos(&self) -> Result<(i32, i32), ObsError> {
145 #[cfg(windows)]
146 if let Some(m) = self.child_window_handler.as_ref() {
147 let m = m
148 .read()
149 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
150 return Ok((m.x, m.y));
151 }
152
153 let pos = DISPLAY_POSITIONS
154 .read()
155 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
156 let pos = pos
157 .get(&self.id)
158 .ok_or_else(|| ObsError::LockError("Position not found".to_string()))?;
159
160 Ok(*pos)
161 }
162
163 fn get_size(&self) -> Result<(u32, u32), ObsError> {
164 #[cfg(windows)]
165 if let Some(m) = self.child_window_handler.as_ref() {
166 let m = m
167 .read()
168 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
169
170 return Ok((m.width, m.height));
171 }
172
173 let pointer = self.display.clone();
174 let (width, height) = run_with_obs!(self.runtime, (pointer), move || unsafe {
175 let mut w: u32 = 0;
176 let mut h: u32 = 0;
177
178 libobs::obs_display_size(pointer, &mut w, &mut h);
179 (w, h)
180 })
181 .map_err(|e| ObsError::InvocationError(format!("{:?}", e)))?;
182
183 Ok((width, height))
184 }
185}