Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: options to disable individual window controls, closes #116 #574

Merged
merged 28 commits into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e75a415
feat(window): implement `minimizable` and `closable` for macOS
caesar Sep 29, 2022
ddb9f2b
feat(window): examples for `minimizable` and `closable`
caesar Sep 29, 2022
d88a1e0
fix(window): stub `minimizable` and `resizable` for other platforms
caesar Sep 29, 2022
bc24307
lint: run cargo fmt
caesar Sep 29, 2022
78922f5
feat(window): implement `closable` for Linux
caesar Oct 2, 2022
1ef6498
refactor: rename parameter
caesar Oct 2, 2022
d6bb6bf
feat(window): implement `maximizable` for macOS
caesar Oct 4, 2022
458d835
feat(window): implement `minimizable` for Windows
kleincyber Oct 4, 2022
d78a27c
fix: edit bitflag for minimizable and move line
kleincyber Oct 6, 2022
e99ce60
fix(window): initial `minimzable` value on Windows
caesar Oct 7, 2022
486e837
feat(window): implement `maximizable` for Windows
caesar Oct 7, 2022
6a70db6
docs(window): correct platform-specific notes
caesar Oct 7, 2022
db72a71
feat(window): implement `closable` for Windows
caesar Oct 8, 2022
4bd48ab
fix(window): missing `mut`
caesar Oct 8, 2022
9311888
chore: add changefile
caesar Oct 8, 2022
0cdb86c
docs(window): correct platform-specific notes
caesar Oct 8, 2022
785a970
docs(window): improve docs for window control toggles
caesar Oct 10, 2022
504c1b6
refactor (examples): move window control examples into window_debug.rs
caesar Oct 10, 2022
f86d04f
refactor(window): move `set_closable` impl on Windows to `WindowFlags…
caesar Oct 10, 2022
0d13731
chore: cargo fmt
caesar Oct 10, 2022
33815f3
chore: update changefile
caesar Oct 10, 2022
6c2df8a
chore: remove println
caesar Oct 10, 2022
50a2b87
fix with_closable on Windows
amrbashir Oct 11, 2022
cb3858c
Update src/platform_impl/linux/window.rs
amrbashir Oct 11, 2022
dd26f66
Update src/platform_impl/linux/window.rs
amrbashir Oct 11, 2022
b47d60b
Update src/window.rs
amrbashir Oct 11, 2022
ae89533
Merge branch 'dev' into disable-window-controls
amrbashir Oct 11, 2022
2372e45
update flags
amrbashir Oct 11, 2022
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
5 changes: 5 additions & 0 deletions .changes/window-controls-disable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": patch
---

Add APIs for disabling the individual window controls on desktop platforms, `Window::set_closable`, `Window::is_closable`, `WindowBuilder::with_closable`, `Window::set_minimizable`, `Window::is_minimizable`, `WindowBuilder::with_minimizable`, `Window::set_maximizable`, `Window::is_maximizable`, `WindowBuilder::with_maximizable`. See the docs for platform-specific notes, especially regarding Linux.
29 changes: 19 additions & 10 deletions examples/window_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ fn main() {
eprintln!("debugging keys:");
eprintln!(" (E) Enter exclusive fullscreen");
eprintln!(" (F) Toggle borderless fullscreen");
eprintln!(" (P) Toggle borderless fullscreen on system's preffered monitor");
eprintln!(" (M) Toggle minimized");
eprintln!(" (Q) Quit event loop");
eprintln!(" (P) Toggle borderless fullscreen on system's preferred monitor");
eprintln!(" (V) Toggle visibility");
eprintln!(" (X) Toggle maximized");
eprintln!(" (T) Toggle always on top");
eprintln!(" (B) Toggle always on bottom");
eprintln!(" (C) Toggle content protection");
eprintln!(" (M) Toggle minimized");
eprintln!(" (X) Toggle maximized");
eprintln!(" (Q) Quit event loop");
eprintln!(" (Shift + M) Toggle minimizable");
eprintln!(" (Shift + X) Toggle maximizable");
eprintln!(" (Shift + Q) Toggle closable");

let mut always_on_bottom = false;
let mut always_on_top = false;
Expand Down Expand Up @@ -139,19 +142,25 @@ fn main() {
content_protection = !content_protection;
window.set_content_protection(content_protection);
}
"M" => {
let minimizable = !window.is_minimizable();
window.set_minimizable(minimizable);
}
"X" => {
let maximizable = !window.is_maximizable();
window.set_maximizable(maximizable);
}
"Q" => {
let closable = !window.is_closable();
window.set_closable(closable);
}
_ => (),
},
Event::WindowEvent {
event: WindowEvent::CloseRequested,
window_id,
..
} if window_id == window.id() => *control_flow = ControlFlow::Exit,
Event::WindowEvent {
event: WindowEvent::Focused(focused),
..
} => {
dbg!(focused, window.is_focused());
}
_ => (),
}
});
Expand Down
35 changes: 32 additions & 3 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,21 @@ 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_maximizable(&self, _maximizable: bool) {
warn!("`Window::set_maximizable` 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 @@ -619,12 +633,27 @@ 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_maximizable(&self) -> bool {
warn!("`Window::is_maximizable` is ignored on Android");
false
}

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

Expand Down
27 changes: 27 additions & 0 deletions src/platform_impl/ios/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,18 @@ 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_maximizable(&self, _maximizable: bool) {
warn!("`Window::set_maximizable` 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 @@ -236,6 +248,21 @@ impl Inner {
false
}

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

pub fn is_maximizable(&self) -> bool {
warn!("`Window::is_maximizable` 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
33 changes: 33 additions & 0 deletions src/platform_impl/linux/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,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 @@ -473,6 +474,23 @@ impl Window {
}
}

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

pub fn set_maximizable(&self, _maximizable: bool) {
warn!("`Window::set_maximizable` is ignored on Linux")
}
amrbashir marked this conversation as resolved.
Show resolved Hide resolved

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 @@ -503,6 +521,20 @@ impl Window {
self.window.is_resizable()
}

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

pub fn is_maximizable(&self) -> bool {
warn!("`Window::is_maximizable` is ignored on Linux");
false
}
amrbashir marked this conversation as resolved.
Show resolved Hide resolved

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

pub fn is_decorated(&self) -> bool {
self.window.is_decorated()
}
Expand Down Expand Up @@ -754,6 +786,7 @@ pub enum WindowRequest {
Visible(bool),
Focus,
Resizable(bool),
Closable(bool),
Minimized(bool),
Maximized(bool),
DragWindow,
Expand Down
69 changes: 69 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 @@ -247,6 +255,11 @@ fn create_window(
];
}

if !attrs.maximizable {
let button = ns_window.standardWindowButton_(NSWindowButton::NSWindowZoomButton);
let _: () = msg_send![button, setEnabled: NO];
}

if let Some(increments) = pl_attrs.resize_increments {
let (x, y) = (increments.width, increments.height);
if x >= 1.0 && y >= 1.0 {
Expand Down Expand Up @@ -693,6 +706,38 @@ 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_maximizable(&self, maximizable: bool) {
unsafe {
let button = self
.ns_window
.standardWindowButton_(NSWindowButton::NSWindowZoomButton);
let _: () = msg_send![button, setEnabled: maximizable];
}
}

#[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 @@ -886,6 +931,30 @@ 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_maximizable(&self) -> bool {
let is_maximizable: BOOL;
unsafe {
let button = self
.ns_window
.standardWindowButton_(NSWindowButton::NSWindowZoomButton);
is_maximizable = msg_send![button, isEnabled];
}
is_maximizable == 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
Loading