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;
69 SetWindowPos(
71 m.window_handle.get_hwnd(),
72 Some(insert_after),
73 x,
74 y,
75 1_i32,
76 1_i32,
77 flags,
78 )
79 .map_err(|e| ObsError::DisplayCreationError(format!("{:?}", e)))?;
80 }
81
82 drop(m); self.update_color_space()?;
85 return Ok(());
86 }
87
88 *DISPLAY_POSITIONS
89 .write()
90 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?
91 .get_mut(&self.id)
92 .ok_or_else(|| ObsError::LockError("Position not found".to_string()))? = (x, y);
93
94 self.update_color_space()?;
95 Ok(())
96 }
97
98 fn set_size(&self, width: u32, height: u32) -> Result<(), ObsError> {
99 log::trace!("Set size {width} {height}");
100
101 #[cfg(windows)]
102 if let Some(m) = self.child_window_handler.as_ref() {
103 let mut m = m
104 .write()
105 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
106
107 assert!(
108 m.obs_display.is_some(),
109 "Invalid state. The display should have been created and set, but it wasn't."
110 );
111
112 m.width = width;
113 m.height = height;
114
115 unsafe {
116 SetWindowPos(
119 m.window_handle.get_hwnd(),
120 None,
121 m.x,
122 m.y,
123 width as i32,
124 height as i32,
125 SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW,
126 )
127 .map_err(|e| ObsError::DisplayCreationError(format!("{:?}", e)))?;
128
129 let _ = RedrawWindow(
130 Some(m.window_handle.get_hwnd()),
131 None,
132 None,
133 RDW_ERASE | RDW_INVALIDATE,
134 );
135 }
136 }
137
138 let pointer = self.as_ptr();
139 run_with_obs!(self.runtime, (pointer), move || {
140 unsafe {
141 libobs::obs_display_resize(pointer.get_ptr(), width, height);
144 libobs::obs_display_update_color_space(pointer.get_ptr());
146 }
147 })
148 .map_err(|e| ObsError::InvocationError(format!("{:?}", e)))?;
149 Ok(())
150 }
151
152 fn get_pos(&self) -> Result<(i32, i32), ObsError> {
153 #[cfg(windows)]
154 if let Some(m) = self.child_window_handler.as_ref() {
155 let m = m
156 .read()
157 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
158 return Ok((m.x, m.y));
159 }
160
161 let pos = DISPLAY_POSITIONS
162 .read()
163 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
164 let pos = pos
165 .get(&self.id)
166 .ok_or_else(|| ObsError::LockError("Position not found".to_string()))?;
167
168 Ok(*pos)
169 }
170
171 fn get_size(&self) -> Result<(u32, u32), ObsError> {
172 #[cfg(windows)]
173 if let Some(m) = self.child_window_handler.as_ref() {
174 let m = m
175 .read()
176 .map_err(|e| ObsError::LockError(format!("{:?}", e)))?;
177
178 return Ok((m.width, m.height));
179 }
180
181 let pointer = self.as_ptr();
182 let (width, height) = run_with_obs!(self.runtime, (pointer), move || {
183 let mut w: u32 = 0;
184 let mut h: u32 = 0;
185 unsafe {
186 libobs::obs_display_size(pointer.get_ptr(), &mut w, &mut h);
188 };
189
190 (w, h)
191 })
192 .map_err(|e| ObsError::InvocationError(format!("{:?}", e)))?;
193
194 Ok((width, height))
195 }
196}