Skip to content

Commit 35d0db2

Browse files
authored
Implement show() and hide() functions (#299)
1 parent f75f9ab commit 35d0db2

11 files changed

Lines changed: 128 additions & 15 deletions

File tree

examples/plugin_clack/src/gui.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ impl PluginGuiImpl for ExamplePluginMainThread<'_> {
114114
let parent = unsafe { raw_window_handle::WindowHandle::borrow_raw(parent) };
115115

116116
gui.handle.set_parent(&parent)?;
117+
gui.handle.show()?;
117118

118119
Ok(())
119120
}
@@ -127,11 +128,21 @@ impl PluginGuiImpl for ExamplePluginMainThread<'_> {
127128
}
128129

129130
fn show(&mut self) -> Result<(), PluginError> {
130-
Ok(()) // Not supported yet
131+
let Some(gui) = &self.gui else {
132+
return Err(PluginError::Message("show called without a GUI active"));
133+
};
134+
gui.handle.show()?;
135+
136+
Ok(())
131137
}
132138

133139
fn hide(&mut self) -> Result<(), PluginError> {
134-
Ok(()) // Not supported yet
140+
let Some(gui) = &self.gui else {
141+
return Err(PluginError::Message("hide called without a GUI active"));
142+
};
143+
gui.handle.show()?;
144+
145+
Ok(())
135146
}
136147
}
137148

examples/render_wgpu/src/main.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,27 +134,28 @@ impl WindowHandler for WgpuExample {
134134
let mut surface = self.surface.borrow_mut();
135135

136136
let surface_texture = match surface.get_current_texture() {
137-
wgpu::CurrentSurfaceTexture::Success(texture) => texture,
137+
wgpu::CurrentSurfaceTexture::Success(texture) => Some(texture),
138138
wgpu::CurrentSurfaceTexture::Occluded | wgpu::CurrentSurfaceTexture::Timeout => {
139139
return Ok(())
140140
}
141141
wgpu::CurrentSurfaceTexture::Suboptimal(_) | wgpu::CurrentSurfaceTexture::Outdated => {
142-
surface.configure(&self.device, &self.surface_config.borrow());
143-
// We'll retry next frame
144-
return Ok(());
142+
None
145143
}
146144
wgpu::CurrentSurfaceTexture::Lost => {
147145
*surface = self.instance.create_surface(self.window_context.platform_handle())?;
148-
surface.configure(&self.device, &self.surface_config.borrow());
149-
150-
// We'll retry next frame
151-
return Ok(());
146+
None
152147
}
153148
wgpu::CurrentSurfaceTexture::Validation => {
154149
unreachable!("No error scope registered, so validation errors will panic")
155150
}
156151
};
157152

153+
let Some(surface_texture) = surface_texture else {
154+
surface.configure(&self.device, &self.surface_config.borrow());
155+
// We'll retry next frame
156+
return Ok(());
157+
};
158+
158159
let view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default());
159160

160161
let mut encoder =

src/platform/macos/view.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,26 @@ impl BaseviewView {
154154
Ok((view, state))
155155
}
156156

157+
pub fn show(this: ViewRef<Self>) {
158+
let Ok(parent) = this.parenting.try_borrow() else { return };
159+
160+
if let ViewParentingType::Windowed { owned_window } = &*parent {
161+
if let Some(window) = owned_window.load() {
162+
window.makeKeyAndOrderFront(None)
163+
}
164+
}
165+
}
166+
167+
pub fn hide(this: ViewRef<Self>) {
168+
let Ok(parent) = this.parenting.try_borrow() else { return };
169+
170+
if let ViewParentingType::Windowed { owned_window } = &*parent {
171+
if let Some(window) = owned_window.load() {
172+
window.orderOut(None)
173+
}
174+
}
175+
}
176+
157177
pub fn close(this: ViewRef<Self>, from_host: bool) {
158178
this.state.closed.set(true);
159179
this.view.removeFromSuperview();

src/platform/macos/window.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ impl WindowHandle {
9393
let Some(view) = self.view.load() else { return Ok(()) };
9494
let Some(view) = view.inner_ref() else { return Ok(()) };
9595

96+
BaseviewView::show(view);
97+
9698
let app = NSApplication::sharedApplication(self.mtm);
9799

98100
view.lifetime_tied_to_app.set(Some(Weak::from_retained(&app)));
@@ -137,6 +139,22 @@ impl WindowHandle {
137139

138140
Ok(())
139141
}
142+
143+
pub fn show(&self) -> Result<()> {
144+
let Some(view) = self.view.load() else { return Ok(()) };
145+
let Some(view) = view.inner_ref() else { return Ok(()) };
146+
147+
BaseviewView::show(view);
148+
Ok(())
149+
}
150+
151+
pub fn hide(&self) -> Result<()> {
152+
let Some(view) = self.view.load() else { return Ok(()) };
153+
let Some(view) = view.inner_ref() else { return Ok(()) };
154+
155+
BaseviewView::hide(view);
156+
Ok(())
157+
}
140158
}
141159

142160
fn create_window_with_options(
@@ -154,7 +172,6 @@ fn create_window_with_options(
154172
let title = NSString::from_str(&options.title);
155173
window.setTitle(&title);
156174

157-
window.makeKeyAndOrderFront(None);
158175
window
159176
}
160177

src/platform/win/window.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ pub struct WindowHandle {
5858

5959
impl WindowHandle {
6060
pub fn run_until_closed(self) -> Result<()> {
61+
self.show()?;
62+
6163
run_thread_message_loop_until(|| !self.is_open())?;
6264
Ok(())
6365
}
@@ -135,6 +137,20 @@ impl WindowHandle {
135137
pub fn handle_main_thread_callback(&self) {
136138
// No-op
137139
}
140+
141+
pub fn show(&self) -> Result<()> {
142+
let Some(hwnd) = self.hwnd.get() else { return Ok(()) };
143+
hwnd.show_and_activate();
144+
145+
Ok(())
146+
}
147+
148+
pub fn hide(&self) -> Result<()> {
149+
let Some(hwnd) = self.hwnd.get() else { return Ok(()) };
150+
hwnd.hide();
151+
152+
Ok(())
153+
}
138154
}
139155

140156
impl Drop for WindowHandle {
@@ -598,8 +614,6 @@ impl WindowHandle {
598614
// TODO: create a new timer instead of hard-coding a specific ID
599615
window.set_timer(WIN_FRAME_TIMER, 15)?;
600616

601-
window.show_and_activate();
602-
603617
Ok(WindowHandle { hwnd: Some(window).into(), state: shared_state })
604618
}
605619
}

src/platform/x11/event_loop.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,14 @@ impl EventLoop {
206206

207207
Ok(())
208208
}
209+
WindowThreadRequest::Show => {
210+
self.window.xcb_window.map_window()?.check()?;
211+
Ok(())
212+
}
213+
WindowThreadRequest::Hide => {
214+
self.window.xcb_window.unmap_window()?.check()?;
215+
Ok(())
216+
}
209217
}
210218
}
211219

src/platform/x11/window_shared.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ impl WindowInner {
9696
)?;
9797

9898
let cookies = [
99-
xcb_window.map_window()?,
10099
xcb_window.set_title(&options.title)?,
101100
xcb_window.enable_wm_protocols()?,
102101
xcb_window.enable_dnd_protocols()?,

src/platform/x11/window_thread.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ pub enum WindowThreadRequest {
7070
SuggestScaleFactor(f64),
7171
Resize(Size),
7272
SetParent(ParentWindowHandle),
73+
Show,
74+
Hide,
7375
}
7476

7577
pub type WindowThreadResponseMessage = core::result::Result<(), String>;
@@ -158,6 +160,8 @@ impl WindowThreadHandle {
158160
}
159161

160162
pub fn run_until_closed(&self) -> Result<()> {
163+
self.request(WindowThreadRequest::Show)?;
164+
161165
let Some(thread) = self.event_loop_handle.take() else { return Ok(()) };
162166

163167
if let Err(panic) = thread.join() {
@@ -171,6 +175,14 @@ impl WindowThreadHandle {
171175
Ok(())
172176
}
173177

178+
pub fn show(&self) -> Result<()> {
179+
self.request(WindowThreadRequest::Show)
180+
}
181+
182+
pub fn hide(&self) -> Result<()> {
183+
self.request(WindowThreadRequest::Hide)
184+
}
185+
174186
pub fn is_open(&self) -> bool {
175187
!self.shared.stopped.load(Ordering::Relaxed)
176188
}

src/platform/x11/xcb_window.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ impl XcbWindow {
6565
Ok(self.connection.conn.map_window(self.window_id.get())?)
6666
}
6767

68+
pub fn unmap_window(&self) -> Result<VoidCookie<'_, XCBConnection>, ReplyOrIdError> {
69+
Ok(self.connection.conn.unmap_window(self.window_id.get())?)
70+
}
71+
6872
pub fn resize(
6973
&self, size: PhysicalSize<u32>,
7074
) -> Result<VoidCookie<'_, XCBConnection>, ConnectionError> {

src/window.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ impl WindowHandle {
1717
Self { window_handle, phantom: PhantomData }
1818
}
1919

20+
/// Blocks the thread and runs an event loop until the window is closed.
21+
///
22+
/// The window is shown automatically if it wasn't already.
2023
#[inline]
2124
pub fn run_until_closed(self) -> Result<(), Error> {
2225
self.window_handle.run_until_closed()?;
@@ -92,11 +95,31 @@ impl WindowHandle {
9295
self.window_handle.handle_main_thread_callback()
9396
}
9497

98+
/// Reparents this window using the given `parent`.
99+
///
100+
/// If the window was a floating window, it will become parented.
95101
#[inline]
96102
pub fn set_parent(&self, parent: impl Into<ParentWindowHandle>) -> Result<(), Error> {
97103
self.window_handle.set_parent(parent.into().inner)?;
98104
Ok(())
99105
}
106+
107+
/// Shows the window to the screen.
108+
#[inline]
109+
pub fn show(&self) -> Result<(), Error> {
110+
self.window_handle.show()?;
111+
Ok(())
112+
}
113+
114+
/// Hides the window from the screen.
115+
///
116+
/// The window will still exist, and it might still receive some events, but rendering will be
117+
/// paused and the user will not be able to see or interact with it.
118+
#[inline]
119+
pub fn hide(&self) -> Result<(), Error> {
120+
self.window_handle.hide()?;
121+
Ok(())
122+
}
100123
}
101124

102125
#[inline]

0 commit comments

Comments
 (0)