Add WindowBuilder::with_active

Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
This commit is contained in:
Amr Bashir 2023-01-27 07:08:29 +02:00 committed by GitHub
parent 930df0ec45
commit b457329003
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 60 additions and 5 deletions

View file

@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre
# Unreleased # Unreleased
- On Windows and macOS, add `WindowBuilder::with_active`.
- Add `Window::is_minimized`. - Add `Window::is_minimized`.
- On X11, fix errors handled during `register_xlib_error_hook` invocation bleeding into winit. - On X11, fix errors handled during `register_xlib_error_hook` invocation bleeding into winit.
- Add `Window::has_focus`. - Add `Window::has_focus`.

View file

@ -511,7 +511,24 @@ impl<T: 'static> EventProcessor<T> {
window.invalidate_cached_frame_extents(); window.invalidate_cached_frame_extents();
}); });
} }
ffi::MapNotify => {
let xev: &ffi::XMapEvent = xev.as_ref();
let window = xev.window;
let window_id = mkwid(window);
// XXX re-issue the focus state when mapping the window.
//
// The purpose of it is to deliver initial focused state of the newly created
// window, given that we can't rely on `CreateNotify`, due to it being not
// sent.
let focus = self
.with_window(window, |window| window.has_focus())
.unwrap_or_default();
callback(Event::WindowEvent {
window_id,
event: WindowEvent::Focused(focus),
});
}
ffi::DestroyNotify => { ffi::DestroyNotify => {
let xev: &ffi::XDestroyWindowEvent = xev.as_ref(); let xev: &ffi::XDestroyWindowEvent = xev.as_ref();

View file

@ -95,7 +95,7 @@ impl SharedState {
max_inner_size: None, max_inner_size: None,
resize_increments: None, resize_increments: None,
base_size: None, base_size: None,
has_focus: true, has_focus: false,
}) })
} }
} }

View file

@ -114,6 +114,9 @@ extern_methods!(
#[sel(makeKeyAndOrderFront:)] #[sel(makeKeyAndOrderFront:)]
pub fn makeKeyAndOrderFront(&self, sender: Option<&Object>); pub fn makeKeyAndOrderFront(&self, sender: Option<&Object>);
#[sel(orderFront:)]
pub fn orderFront(&self, sender: Option<&Object>);
#[sel(miniaturize:)] #[sel(miniaturize:)]
pub fn miniaturize(&self, sender: Option<&Object>); pub fn miniaturize(&self, sender: Option<&Object>);

View file

@ -19,6 +19,7 @@ use crate::{
LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size, Size::Logical, LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size, Size::Logical,
}, },
error::{ExternalError, NotSupportedError, OsError as RootOsError}, error::{ExternalError, NotSupportedError, OsError as RootOsError},
event::WindowEvent,
icon::Icon, icon::Icon,
platform::macos::WindowExtMacOS, platform::macos::WindowExtMacOS,
platform_impl::platform::{ platform_impl::platform::{
@ -464,14 +465,20 @@ impl WinitWindow {
// state, since otherwise we'll briefly see the window at normal size // state, since otherwise we'll briefly see the window at normal size
// before it transitions. // before it transitions.
if attrs.visible { if attrs.visible {
if attrs.active {
// Tightly linked with `app_state::window_activation_hack` // Tightly linked with `app_state::window_activation_hack`
this.makeKeyAndOrderFront(None); this.makeKeyAndOrderFront(None);
} else {
this.orderFront(None);
}
} }
if attrs.maximized { if attrs.maximized {
this.set_maximized(attrs.maximized); this.set_maximized(attrs.maximized);
} }
delegate.queue_event(WindowEvent::Focused(false));
Ok((this, delegate)) Ok((this, delegate))
} }

View file

@ -406,7 +406,7 @@ impl WinitWindowDelegate {
} }
} }
fn queue_event(&self, event: WindowEvent<'static>) { pub(crate) fn queue_event(&self, event: WindowEvent<'static>) {
let event = Event::WindowEvent { let event = Event::WindowEvent {
window_id: WindowId(self.window.id()), window_id: WindowId(self.window.id()),
event, event,

View file

@ -1076,6 +1076,7 @@ where
WindowFlags::NO_BACK_BUFFER, WindowFlags::NO_BACK_BUFFER,
pl_attribs.no_redirection_bitmap, pl_attribs.no_redirection_bitmap,
); );
window_flags.set(WindowFlags::MARKER_ACTIVATE, attributes.active);
window_flags.set(WindowFlags::TRANSPARENT, attributes.transparent); window_flags.set(WindowFlags::TRANSPARENT, attributes.transparent);
// WindowFlags::VISIBLE and MAXIMIZED are set down below after the window has been configured. // WindowFlags::VISIBLE and MAXIMIZED are set down below after the window has been configured.
window_flags.set(WindowFlags::RESIZABLE, attributes.resizable); window_flags.set(WindowFlags::RESIZABLE, attributes.resizable);

View file

@ -116,6 +116,8 @@ bitflags! {
/// Drop shadow for undecorated windows. /// Drop shadow for undecorated windows.
const MARKER_UNDECORATED_SHADOW = 1 << 20; const MARKER_UNDECORATED_SHADOW = 1 << 20;
const MARKER_ACTIVATE = 1 << 18;
const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits; const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits;
} }
} }
@ -306,8 +308,14 @@ impl WindowFlags {
} }
if new.contains(WindowFlags::VISIBLE) { if new.contains(WindowFlags::VISIBLE) {
let flag = !if self.contains(WindowFlags::MARKER_ACTIVATE) {
self.set(WindowFlags::MARKER_ACTIVATE, true);
SWP_NOACTIVATE
} else {
SW_SHOW
};
unsafe { unsafe {
ShowWindow(window, SW_SHOW); ShowWindow(window, flag);
} }
} }

View file

@ -139,6 +139,7 @@ pub(crate) struct WindowAttributes {
pub content_protected: bool, pub content_protected: bool,
pub window_level: WindowLevel, pub window_level: WindowLevel,
pub parent_window: Option<RawWindowHandle>, pub parent_window: Option<RawWindowHandle>,
pub active: bool,
} }
impl Default for WindowAttributes { impl Default for WindowAttributes {
@ -163,6 +164,7 @@ impl Default for WindowAttributes {
resize_increments: None, resize_increments: None,
content_protected: false, content_protected: false,
parent_window: None, parent_window: None,
active: true,
} }
} }
} }
@ -405,6 +407,22 @@ impl WindowBuilder {
self self
} }
/// Whether the window will be initially focused or not.
///
/// The window should be assumed as not focused by default
/// following by the [`WindowEvent::Focused`].
///
/// ## Platform-specific:
///
/// **Android / iOS / X11 / Wayland / Orbital:** Unsupported.
///
/// [`WindowEvent::Focused`]: crate::event::WindowEvent::Focused.
#[inline]
pub fn with_active(mut self, active: bool) -> WindowBuilder {
self.window.active = active;
self
}
/// Build window with parent window. /// Build window with parent window.
/// ///
/// The default is `None`. /// The default is `None`.