Window::set_minimized (#985) (#990)

* Expose set_minimized. Implement for macOS (#985)

* Implement set_minimized for Wayland (#985)

Co-Authored-By: Victor Berger <vberger@users.noreply.github.com>

* Implement set_minimized for Windows (#985)

* Remove debug logs (#985)

* Implement Window::set_minimized for X11

* Remove extra param from set_window_flags call

* Cargo fmt

* Add example of usage

* Update changelog

* Update feature matrix

* Cargo fmt

* Update example to remove unnecessary event var

* Stop setting window styles when minimizing (#985)

* Add stub for WASM (#985)

Co-authored-by: Victor Berger <vberger@users.noreply.github.com>
Co-authored-by: Murarth <murarth@gmail.com>
Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
Co-authored-by: Osspial <osspial@gmail.com>
This commit is contained in:
Justin Miller 2019-12-22 01:04:11 -05:00 committed by Osspial
parent 92741aa4ec
commit 82889e2367
14 changed files with 172 additions and 2 deletions

View file

@ -360,6 +360,11 @@ impl Window {
Err(ExternalError::NotSupported(NotSupportedError::new()))
}
#[inline]
pub fn set_minimized(&self, _minimized: bool) {
unimplemented!()
}
#[inline]
pub fn set_maximized(&self, _maximized: bool) {
// N/A

View file

@ -169,6 +169,10 @@ impl Inner {
debug!("`Window::set_cursor_visible` is ignored on iOS")
}
pub fn set_minimized(&self, _minimized: bool) {
warn!("`Window::set_minimized` is ignored on iOS")
}
pub fn set_maximized(&self, _maximized: bool) {
warn!("`Window::set_maximized` is ignored on iOS")
}

View file

@ -367,6 +367,14 @@ impl Window {
}
}
#[inline]
pub fn set_minimized(&self, minimized: bool) {
match self {
&Window::X(ref w) => w.set_minimized(minimized),
&Window::Wayland(ref w) => w.set_minimized(minimized),
}
}
#[inline]
pub fn fullscreen(&self) -> Option<Fullscreen> {
match self {

View file

@ -259,6 +259,13 @@ impl Window {
*(self.need_frame_refresh.lock().unwrap()) = true;
}
pub fn set_minimized(&self, minimized: bool) {
// An app cannot un-minimize itself on Wayland
if minimized {
self.frame.lock().unwrap().set_minimized();
}
}
pub fn set_maximized(&self, maximized: bool) {
if maximized {
self.frame.lock().unwrap().set_maximized();

View file

@ -749,6 +749,35 @@ impl UnownedWindow {
self.xconn.primary_monitor()
}
fn set_minimized_inner(&self, minimized: bool) -> util::Flusher<'_> {
unsafe {
if minimized {
let screen = (self.xconn.xlib.XDefaultScreen)(self.xconn.display);
(self.xconn.xlib.XIconifyWindow)(self.xconn.display, self.xwindow, screen);
util::Flusher::new(&self.xconn)
} else {
let atom = self.xconn.get_atom_unchecked(b"_NET_ACTIVE_WINDOW\0");
self.xconn.send_client_msg(
self.xwindow,
self.root,
atom,
Some(ffi::SubstructureRedirectMask | ffi::SubstructureNotifyMask),
[1, ffi::CurrentTime as c_long, 0, 0, 0],
)
}
}
}
#[inline]
pub fn set_minimized(&self, minimized: bool) {
self.set_minimized_inner(minimized)
.flush()
.expect("Failed to change window minimization");
}
fn set_maximized_inner(&self, maximized: bool) -> util::Flusher<'_> {
let horz_atom = unsafe {
self.xconn

View file

@ -617,6 +617,25 @@ impl UnownedWindow {
self.set_maximized(maximized);
}
#[inline]
pub fn set_minimized(&self, minimized: bool) {
let is_minimized: BOOL = unsafe { msg_send![*self.ns_window, isMiniaturized] };
let is_minimized: bool = is_minimized == YES;
if is_minimized == minimized {
return;
}
if minimized {
unsafe {
NSWindow::miniaturize_(*self.ns_window, *self.ns_window);
}
} else {
unsafe {
NSWindow::deminiaturize_(*self.ns_window, *self.ns_window);
}
}
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
let is_zoomed = self.is_zoomed();

View file

@ -199,6 +199,11 @@ impl Window {
}
}
#[inline]
pub fn set_minimized(&self, _minimized: bool) {
// Intentionally a no-op, as canvases cannot be 'minimized'
}
#[inline]
pub fn set_maximized(&self, _maximized: bool) {
// Intentionally a no-op, as canvases cannot be 'maximized'

View file

@ -1145,7 +1145,18 @@ unsafe extern "system" fn public_window_callback<T>(
0
}
// this is necessary for us to maintain minimize/restore state
winuser::WM_SYSCOMMAND => {
if wparam == winuser::SC_RESTORE {
let mut w = subclass_input.window_state.lock();
w.set_window_flags_in_place(|f| f.set(WindowFlags::MINIMIZED, false));
}
if wparam == winuser::SC_MINIMIZE {
let mut w = subclass_input.window_state.lock();
w.set_window_flags_in_place(|f| f.set(WindowFlags::MINIMIZED, true));
}
// Send `WindowEvent::Minimized` here if we decide to implement one
if wparam == winuser::SC_SCREENSAVE {
let window_state = subclass_input.window_state.lock();
if window_state.fullscreen.is_some() {

View file

@ -452,6 +452,18 @@ impl Window {
WindowId(self.window.0)
}
#[inline]
pub fn set_minimized(&self, minimized: 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::MINIMIZED, minimized)
});
});
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
let window = self.window.clone();

View file

@ -79,6 +79,8 @@ bitflags! {
/// window's state to match our stored state. This controls whether to accept those changes.
const MARKER_RETAIN_STATE_ON_SIZE = 1 << 10;
const MINIMIZED = 1 << 11;
const FULLSCREEN_AND_MASK = !(
WindowFlags::DECORATIONS.bits |
WindowFlags::RESIZABLE.bits |
@ -212,6 +214,9 @@ impl WindowFlags {
if self.contains(WindowFlags::CHILD) {
style |= WS_CHILD; // This is incompatible with WS_POPUP if that gets added eventually.
}
if self.contains(WindowFlags::MINIMIZED) {
style |= WS_MINIMIZE;
}
if self.contains(WindowFlags::MAXIMIZED) {
style |= WS_MAXIMIZE;
}
@ -276,14 +281,30 @@ impl WindowFlags {
}
}
// Minimize operations should execute after maximize for proper window animations
if diff.contains(WindowFlags::MINIMIZED) {
unsafe {
winuser::ShowWindow(
window,
match new.contains(WindowFlags::MINIMIZED) {
true => winuser::SW_MINIMIZE,
false => winuser::SW_RESTORE,
},
);
}
}
if diff != WindowFlags::empty() {
let (style, style_ex) = new.to_window_styles();
unsafe {
winuser::SendMessageW(window, *event_loop::SET_RETAIN_STATE_ON_SIZE_MSG_ID, 1, 0);
winuser::SetWindowLongW(window, winuser::GWL_STYLE, style as _);
winuser::SetWindowLongW(window, winuser::GWL_EXSTYLE, style_ex as _);
// This condition is necessary to avoid having an unrestorable window
if !new.contains(WindowFlags::MINIMIZED) {
winuser::SetWindowLongW(window, winuser::GWL_STYLE, style as _);
winuser::SetWindowLongW(window, winuser::GWL_EXSTYLE, style_ex as _);
}
let mut flags = winuser::SWP_NOZORDER
| winuser::SWP_NOMOVE