mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 05:21:31 +11:00
* 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
|
@ -1,5 +1,6 @@
|
|||
# Unreleased
|
||||
|
||||
- On all platforms except mobile and WASM, implement `Window::set_minimized`.
|
||||
- On X11, fix `CursorEntered` event being generated for non-winit windows.
|
||||
- On macOS, fix crash when starting maximized without decorations.
|
||||
- On macOS, fix application not to terminate on `run_return`.
|
||||
|
@ -50,6 +51,7 @@
|
|||
- On X11, return dummy monitor data to avoid panicking when no monitors exist.
|
||||
- On X11, prevent stealing input focus when creating a new window.
|
||||
Only steal input focus when entering fullscreen mode.
|
||||
- On Wayland, fixed DeviceEvents for relative mouse movement is not always produced
|
||||
- On Wayland, add support for set_cursor_visible and set_cursor_grab.
|
||||
- On Wayland, fixed DeviceEvents for relative mouse movement is not always produced.
|
||||
- Removed `derivative` crate dependency.
|
||||
|
|
|
@ -80,6 +80,7 @@ If your PR makes notable changes to Winit's features, please update this section
|
|||
- **Window maximization**: The windows created by winit can be maximized upon creation.
|
||||
- **Window maximization toggle**: The windows created by winit can be maximized and unmaximized after
|
||||
creation.
|
||||
- **Window minimization**: The windows created by winit can be minimized after creation.
|
||||
- **Fullscreen**: The windows created by winit can be put into fullscreen mode.
|
||||
- **Fullscreen toggle**: The windows created by winit can be switched to and from fullscreen after
|
||||
creation.
|
||||
|
@ -173,6 +174,7 @@ Legend:
|
|||
|Window transparency |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|N/A |
|
||||
|Window maximization |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|
|
||||
|Window maximization toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|
|
||||
|Window minimization |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A**|
|
||||
|Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |✔️ |
|
||||
|Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |✔️ |
|
||||
|Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |❌ |✔️ |**N/A**|
|
||||
|
|
35
examples/minimize.rs
Normal file
35
examples/minimize.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
extern crate winit;
|
||||
|
||||
use winit::event::{Event, VirtualKeyCode, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::WindowBuilder;
|
||||
|
||||
fn main() {
|
||||
let event_loop = EventLoop::new();
|
||||
|
||||
let window = WindowBuilder::new()
|
||||
.with_title("A fantastic window!")
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| match event {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => *control_flow = ControlFlow::Exit,
|
||||
|
||||
// Keyboard input event to handle minimize via a hotkey
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::KeyboardInput { input, .. },
|
||||
window_id,
|
||||
} => {
|
||||
if window_id == window.id() {
|
||||
// Pressing the 'M' key will minimize the window
|
||||
if input.virtual_keycode == Some(VirtualKeyCode::M) {
|
||||
window.set_minimized(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => *control_flow = ControlFlow::Wait,
|
||||
});
|
||||
}
|
|
@ -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);
|
||||
|
||||
// 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
|
||||
|
|
|
@ -572,6 +572,16 @@ impl Window {
|
|||
self.window.set_resizable(resizable)
|
||||
}
|
||||
|
||||
/// Sets the window to minimized or back
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS:** Has no effect
|
||||
#[inline]
|
||||
pub fn set_minimized(&self, minimized: bool) {
|
||||
self.window.set_minimized(minimized);
|
||||
}
|
||||
|
||||
/// Sets the window to maximized or back.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
|
|
Loading…
Reference in a new issue