Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions examples/plugin_clack/src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ impl PluginGuiImpl for ExamplePluginMainThread<'_> {
let parent = unsafe { raw_window_handle::WindowHandle::borrow_raw(parent) };

gui.handle.set_parent(&parent)?;
gui.handle.show()?;

Ok(())
}
Expand All @@ -127,11 +128,21 @@ impl PluginGuiImpl for ExamplePluginMainThread<'_> {
}

fn show(&mut self) -> Result<(), PluginError> {
Ok(()) // Not supported yet
let Some(gui) = &self.gui else {
return Err(PluginError::Message("show called without a GUI active"));
};
gui.handle.show()?;

Ok(())
}

fn hide(&mut self) -> Result<(), PluginError> {
Ok(()) // Not supported yet
let Some(gui) = &self.gui else {
return Err(PluginError::Message("hide called without a GUI active"));
};
gui.handle.show()?;

Ok(())
}
}

Expand Down
17 changes: 9 additions & 8 deletions examples/render_wgpu/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,27 +134,28 @@ impl WindowHandler for WgpuExample {
let mut surface = self.surface.borrow_mut();

let surface_texture = match surface.get_current_texture() {
wgpu::CurrentSurfaceTexture::Success(texture) => texture,
wgpu::CurrentSurfaceTexture::Success(texture) => Some(texture),
wgpu::CurrentSurfaceTexture::Occluded | wgpu::CurrentSurfaceTexture::Timeout => {
return Ok(())
}
wgpu::CurrentSurfaceTexture::Suboptimal(_) | wgpu::CurrentSurfaceTexture::Outdated => {
surface.configure(&self.device, &self.surface_config.borrow());
// We'll retry next frame
return Ok(());
None
}
wgpu::CurrentSurfaceTexture::Lost => {
*surface = self.instance.create_surface(self.window_context.platform_handle())?;
surface.configure(&self.device, &self.surface_config.borrow());

// We'll retry next frame
return Ok(());
None
}
wgpu::CurrentSurfaceTexture::Validation => {
unreachable!("No error scope registered, so validation errors will panic")
}
};

let Some(surface_texture) = surface_texture else {
surface.configure(&self.device, &self.surface_config.borrow());
// We'll retry next frame
return Ok(());
};

let view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default());

let mut encoder =
Expand Down
20 changes: 20 additions & 0 deletions src/platform/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ impl BaseviewView {
Ok((view, state))
}

pub fn show(this: ViewRef<Self>) {
let Ok(parent) = this.parenting.try_borrow() else { return };

if let ViewParentingType::Windowed { owned_window } = &*parent {
if let Some(window) = owned_window.load() {
window.makeKeyAndOrderFront(None)
}
}
}

pub fn hide(this: ViewRef<Self>) {
let Ok(parent) = this.parenting.try_borrow() else { return };

if let ViewParentingType::Windowed { owned_window } = &*parent {
if let Some(window) = owned_window.load() {
window.orderOut(None)
}
}
}

pub fn close(this: ViewRef<Self>, from_host: bool) {
this.state.closed.set(true);
this.view.removeFromSuperview();
Expand Down
19 changes: 18 additions & 1 deletion src/platform/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ impl WindowHandle {
let Some(view) = self.view.load() else { return Ok(()) };
let Some(view) = view.inner_ref() else { return Ok(()) };

BaseviewView::show(view);

let app = NSApplication::sharedApplication(self.mtm);

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

Ok(())
}

pub fn show(&self) -> Result<()> {
let Some(view) = self.view.load() else { return Ok(()) };
let Some(view) = view.inner_ref() else { return Ok(()) };

BaseviewView::show(view);
Ok(())
}

pub fn hide(&self) -> Result<()> {
let Some(view) = self.view.load() else { return Ok(()) };
let Some(view) = view.inner_ref() else { return Ok(()) };

BaseviewView::hide(view);
Ok(())
}
}

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

window.makeKeyAndOrderFront(None);
window
}

Expand Down
18 changes: 16 additions & 2 deletions src/platform/win/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub struct WindowHandle {

impl WindowHandle {
pub fn run_until_closed(self) -> Result<()> {
self.show()?;

run_thread_message_loop_until(|| !self.is_open())?;
Ok(())
}
Expand Down Expand Up @@ -135,6 +137,20 @@ impl WindowHandle {
pub fn handle_main_thread_callback(&self) {
// No-op
}

pub fn show(&self) -> Result<()> {
let Some(hwnd) = self.hwnd.get() else { return Ok(()) };
hwnd.show_and_activate();

Ok(())
}

pub fn hide(&self) -> Result<()> {
let Some(hwnd) = self.hwnd.get() else { return Ok(()) };
hwnd.hide();

Ok(())
}
}

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

window.show_and_activate();

Ok(WindowHandle { hwnd: Some(window).into(), state: shared_state })
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/platform/x11/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ impl EventLoop {

Ok(())
}
WindowThreadRequest::Show => {
self.window.xcb_window.map_window()?.check()?;
Ok(())
}
WindowThreadRequest::Hide => {
self.window.xcb_window.unmap_window()?.check()?;
Ok(())
}
}
}

Expand Down
1 change: 0 additions & 1 deletion src/platform/x11/window_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ impl WindowInner {
)?;

let cookies = [
xcb_window.map_window()?,
xcb_window.set_title(&options.title)?,
xcb_window.enable_wm_protocols()?,
xcb_window.enable_dnd_protocols()?,
Expand Down
12 changes: 12 additions & 0 deletions src/platform/x11/window_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ pub enum WindowThreadRequest {
SuggestScaleFactor(f64),
Resize(Size),
SetParent(ParentWindowHandle),
Show,
Hide,
}

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

pub fn run_until_closed(&self) -> Result<()> {
self.request(WindowThreadRequest::Show)?;

let Some(thread) = self.event_loop_handle.take() else { return Ok(()) };

if let Err(panic) = thread.join() {
Expand All @@ -171,6 +175,14 @@ impl WindowThreadHandle {
Ok(())
}

pub fn show(&self) -> Result<()> {
self.request(WindowThreadRequest::Show)
}

pub fn hide(&self) -> Result<()> {
self.request(WindowThreadRequest::Hide)
}

pub fn is_open(&self) -> bool {
!self.shared.stopped.load(Ordering::Relaxed)
}
Expand Down
4 changes: 4 additions & 0 deletions src/platform/x11/xcb_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ impl XcbWindow {
Ok(self.connection.conn.map_window(self.window_id.get())?)
}

pub fn unmap_window(&self) -> Result<VoidCookie<'_, XCBConnection>, ReplyOrIdError> {
Ok(self.connection.conn.unmap_window(self.window_id.get())?)
}

pub fn resize(
&self, size: PhysicalSize<u32>,
) -> Result<VoidCookie<'_, XCBConnection>, ConnectionError> {
Expand Down
23 changes: 23 additions & 0 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ impl WindowHandle {
Self { window_handle, phantom: PhantomData }
}

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

/// Reparents this window using the given `parent`.
///
/// If the window was a floating window, it will become parented.
#[inline]
pub fn set_parent(&self, parent: impl Into<ParentWindowHandle>) -> Result<(), Error> {
self.window_handle.set_parent(parent.into().inner)?;
Ok(())
}

/// Shows the window to the screen.
#[inline]
pub fn show(&self) -> Result<(), Error> {
self.window_handle.show()?;
Ok(())
}

/// Hides the window from the screen.
///
/// The window will still exist, and it might still receive some events, but rendering will be
/// paused and the user will not be able to see or interact with it.
#[inline]
pub fn hide(&self) -> Result<(), Error> {
self.window_handle.hide()?;
Ok(())
}
}

#[inline]
Expand Down
6 changes: 5 additions & 1 deletion src/wrappers/win32/window/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use windows_sys::Win32::UI::Input::KeyboardAndMouse::{
use windows_sys::Win32::UI::WindowsAndMessaging::{
DestroyWindow, GetWindowLongPtrW, GetWindowLongW, SetParent, SetTimer, SetWindowLongPtrW,
SetWindowLongW, SetWindowPos, ShowWindow, GWLP_USERDATA, GWL_EXSTYLE, GWL_STYLE,
SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOZORDER, SW_SHOW, WINDOW_LONG_PTR_INDEX,
SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOZORDER, SW_HIDE, SW_SHOW, WINDOW_LONG_PTR_INDEX,
};

/// A simple wrapper around a HWND.
Expand Down Expand Up @@ -193,6 +193,10 @@ impl HWnd {
result != 0
}

pub fn hide(&self) {
unsafe { ShowWindow(self.as_raw(), SW_HIDE) };
}

pub fn set_nc_rect(&self, nc_rect: Rect) -> Result<()> {
let size = nc_rect.size();

Expand Down