* 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:
parent
92741aa4ec
commit
82889e2367
14 changed files with 172 additions and 2 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue