Skip to content
Open
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
51 changes: 51 additions & 0 deletions examples/closable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2014-2021 The winit contributors
// Copyright 2021-2022 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0

use tao::{
dpi::LogicalSize,
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::KeyCode,
window::WindowBuilder,
};

#[allow(clippy::single_match)]
fn main() {
env_logger::init();
let event_loop = EventLoop::new();

// let mut closable = false;

let window = WindowBuilder::new()
.with_title("Hit space to toggle closability.")
.with_inner_size(LogicalSize::new(400.0, 200.0))
.with_closable(false)
.build(&event_loop)
.unwrap();

event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;

match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::KeyboardInput {
event:
KeyEvent {
physical_key: KeyCode::Space,
state: ElementState::Released,
..
},
..
} => {
let closable = !window.is_closable();
println!("closable: {}", closable);
window.set_closable(closable);
}
_ => (),
},
_ => (),
};
});
}
38 changes: 22 additions & 16 deletions examples/minimize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
extern crate tao;

use tao::{
event::{Event, WindowEvent},
event::{ElementState, Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::Key,
window::WindowBuilder,
Expand All @@ -17,7 +17,7 @@ fn main() {
let event_loop = EventLoop::new();

let window = WindowBuilder::new()
.with_title("A fantastic window!")
.with_title("Hit `m` to minimize, `space` to toggle minimizability")
.build(&event_loop)
.unwrap();

Expand All @@ -26,21 +26,27 @@ fn main() {

match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
event, window_id, ..
} if window_id == window.id() => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,

// Keyboard input event to handle minimize via a hotkey
Event::WindowEvent {
event: WindowEvent::KeyboardInput { event, .. },
window_id,
..
} if window_id == window.id() && Key::Character("m") == event.logical_key => {
// Pressing the 'm' key will minimize the window
// WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example
window.set_minimized(true);
}
// Keyboard input event to handle minimize via a hotkey
WindowEvent::KeyboardInput { event, .. } if event.state == ElementState::Pressed => {
match event.logical_key {
// Pressing the 'm' key will minimize the window
// WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example
Key::Character("m") => window.set_minimized(true),
Key::Space => {
let minimizable = !window.is_minimizable();
println!("Minimizable: {}", minimizable);
window.set_minimizable(minimizable);
}
_ => (),
}
}
_ => (),
},
_ => (),
}
});
Expand Down
26 changes: 23 additions & 3 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,17 @@ impl Window {
false
}

pub fn set_resizable(&self, _resizeable: bool) {}
pub fn set_resizable(&self, _resizeable: bool) {
warn!("`Window::set_resizable` is ignored on Android")
}

pub fn set_minimizable(&self, _minimizable: bool) {
warn!("`Window::set_minimizable` is ignored on Android")
}

pub fn set_closable(&self, _closable: bool) {
warn!("`Window::set_closable` is ignored on Android")
}

pub fn set_minimized(&self, _minimized: bool) {}

Expand All @@ -622,12 +632,22 @@ impl Window {
}

pub fn is_visible(&self) -> bool {
log::warn!("`Window::is_visible` is ignored on android");
log::warn!("`Window::is_visible` is ignored on Android");
false
}

pub fn is_resizable(&self) -> bool {
warn!("`Window::is_resizable` is ignored on android");
warn!("`Window::is_resizable` is ignored on Android");
false
}

pub fn is_minimizable(&self) -> bool {
warn!("`Window::is_minimizable` is ignored on Android");
false
}

pub fn is_closable(&self) -> bool {
warn!("`Window::is_closable` is ignored on Android");
false
}

Expand Down
18 changes: 18 additions & 0 deletions src/platform_impl/ios/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ impl Inner {
warn!("`Window::set_resizable` is ignored on iOS")
}

pub fn set_minimizable(&self, _minimizable: bool) {
warn!("`Window::set_minimizable` is ignored on iOS")
}

pub fn set_closable(&self, _closable: bool) {
warn!("`Window::set_closable` is ignored on iOS")
}

pub fn scale_factor(&self) -> f64 {
unsafe {
let hidpi: CGFloat = msg_send![self.view, contentScaleFactor];
Expand Down Expand Up @@ -240,6 +248,16 @@ impl Inner {
false
}

pub fn is_minimizable(&self) -> bool {
warn!("`Window::is_minimizable` is ignored on iOS");
false
}

pub fn is_closable(&self) -> bool {
warn!("`Window::is_closable` is ignored on iOS");
false
}

pub fn is_decorated(&self) -> bool {
warn!("`Window::is_decorated` is ignored on iOS");
false
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/linux/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ impl<T: 'static> EventLoop<T> {
window.present_with_time(gdk_sys::GDK_CURRENT_TIME as _);
}
WindowRequest::Resizable(resizable) => window.set_resizable(resizable),
WindowRequest::Closable(closable) => window.set_deletable(closable),
WindowRequest::Minimized(minimized) => {
if minimized {
window.iconify();
Expand Down
24 changes: 24 additions & 0 deletions src/platform_impl/linux/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ impl Window {
}

window.set_resizable(attributes.resizable);
window.set_deletable(attributes.closable);

// Set Min/Max Size
let geom_mask = (if attributes.min_inner_size.is_some() {
Expand Down Expand Up @@ -498,6 +499,19 @@ impl Window {
}
}

pub fn set_minimizable(&self, _minimizable: bool) {
warn!("`Window::set_minimizable` is ignored on Linux")
}

pub fn set_closable(&self, closable: bool) {
if let Err(e) = self
.window_requests_tx
.send((self.window_id, WindowRequest::Closable(closable)))
{
log::warn!("Fail to send closable request: {}", e);
}
}

pub fn set_minimized(&self, minimized: bool) {
if let Err(e) = self
.window_requests_tx
Expand Down Expand Up @@ -528,6 +542,15 @@ impl Window {
self.window.is_resizable()
}

pub fn is_minimizable(&self) -> bool {
warn!("`Window::is_minimizable` is ignored on Linux");
false
}

pub fn is_closable(&self) -> bool {
self.window.is_deletable()
}

pub fn is_decorated(&self) -> bool {
self.window.is_decorated()
}
Expand Down Expand Up @@ -779,6 +802,7 @@ pub enum WindowRequest {
Visible(bool),
Focus,
Resizable(bool),
Closable(bool),
Minimized(bool),
Maximized(bool),
DragWindow,
Expand Down
42 changes: 42 additions & 0 deletions src/platform_impl/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,14 @@ fn create_window(
masks &= !NSWindowStyleMask::NSResizableWindowMask;
}

if !attrs.minimizable {
masks &= !NSWindowStyleMask::NSMiniaturizableWindowMask;
}

if !attrs.closable {
masks &= !NSWindowStyleMask::NSClosableWindowMask;
}

if pl_attrs.fullsize_content_view {
masks |= NSWindowStyleMask::NSFullSizeContentViewWindowMask;
}
Expand Down Expand Up @@ -705,6 +713,28 @@ impl UnownedWindow {
} // Otherwise, we don't change the mask until we exit fullscreen.
}

#[inline]
pub fn set_minimizable(&self, minimizable: bool) {
let mut mask = unsafe { self.ns_window.styleMask() };
if minimizable {
mask |= NSWindowStyleMask::NSMiniaturizableWindowMask;
} else {
mask &= !NSWindowStyleMask::NSMiniaturizableWindowMask;
}
self.set_style_mask_async(mask);
}

#[inline]
pub fn set_closable(&self, closable: bool) {
let mut mask = unsafe { self.ns_window.styleMask() };
if closable {
mask |= NSWindowStyleMask::NSClosableWindowMask;
} else {
mask &= !NSWindowStyleMask::NSClosableWindowMask;
}
self.set_style_mask_async(mask);
}

pub fn set_cursor_icon(&self, cursor: CursorIcon) {
let cursor = util::Cursor::from(cursor);
if let Some(cursor_access) = self.cursor_state.upgrade() {
Expand Down Expand Up @@ -898,6 +928,18 @@ impl UnownedWindow {
is_resizable == YES
}

#[inline]
pub fn is_minimizable(&self) -> bool {
let is_minimizable: BOOL = unsafe { msg_send![*self.ns_window, isMiniaturizable] };
is_minimizable == YES
}

#[inline]
pub fn is_closable(&self) -> bool {
let is_closable: BOOL = unsafe { msg_send![*self.ns_window, hasCloseBox] };
is_closable == YES
}

#[inline]
pub fn is_decorated(&self) -> bool {
self.decorations.load(Ordering::Acquire)
Expand Down
29 changes: 29 additions & 0 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,23 @@ impl Window {
});
}

#[inline]
pub fn set_minimizable(&self, minimizable: bool) {
let window = self.window.clone();
let window_state = Arc::clone(&self.window_state);

self.thread_executor.execute_in_thread(move || {
WindowState::set_window_flags(window_state.lock(), window.0, |f| {
f.set(WindowFlags::MINIMIZABLE, minimizable)
})
})
}

#[inline]
pub fn set_closable(&self, _closable: bool) {
warn!("`Window::set_closable` is ignored on Windows")
}

/// Returns the `hwnd` of this window.
#[inline]
pub fn hwnd(&self) -> HWND {
Expand Down Expand Up @@ -487,6 +504,18 @@ impl Window {
window_state.window_flags.contains(WindowFlags::RESIZABLE)
}

#[inline]
pub fn is_minimizable(&self) -> bool {
let window_state = self.window_state.lock();
window_state.window_flags.contains(WindowFlags::MINIMIZABLE)
}

#[inline]
pub fn is_closable(&self) -> bool {
warn!("`Window::is_closable` is ignored on Windows");
false
}

#[inline]
pub fn is_decorated(&self) -> bool {
let window_state = self.window_state.lock();
Expand Down
8 changes: 7 additions & 1 deletion src/platform_impl/windows/window_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ bitflags! {
const POPUP = 1 << 9;
const ALWAYS_ON_BOTTOM = 1 << 10;


/// Marker flag for fullscreen. Should always match `WindowState::fullscreen`, but is
/// included here to make masking easier.
const MARKER_EXCLUSIVE_FULLSCREEN = 1 << 11;
Expand All @@ -102,6 +103,8 @@ bitflags! {

const IGNORE_CURSOR_EVENT = 1 << 17;

const MINIMIZABLE = 1 << 18;

const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits;
}
}
Expand Down Expand Up @@ -221,12 +224,15 @@ impl WindowFlags {

pub fn to_window_styles(self) -> (WINDOW_STYLE, WINDOW_EX_STYLE) {
let (mut style, mut style_ex) = (Default::default(), Default::default());
style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX;
style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU | WS_CAPTION;
style_ex |= WS_EX_ACCEPTFILES;

if self.contains(WindowFlags::RESIZABLE) {
style |= WS_SIZEBOX | WS_MAXIMIZEBOX;
}
if self.contains(WindowFlags::MINIMIZABLE) {
style |= WS_MINIMIZEBOX;
}
if self.contains(WindowFlags::DECORATIONS) {
style_ex |= WS_EX_WINDOWEDGE;
}
Expand Down
Loading