mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
Implement ThemeChanged for web target. (#1462)
* Implement ThemeChanged for web target. * Add TODO upstream to stdweb. Co-authored-by: Ryan G <ryanisaacg@users.noreply.github.com>
This commit is contained in:
parent
e88e8bc194
commit
d1073dcecb
|
@ -5,6 +5,7 @@
|
|||
- On Wayland, fix color from `close_button_icon_color` not applying.
|
||||
- Ignore locale if unsupported by X11 backend
|
||||
- On Wayland, Add HiDPI cursor support
|
||||
- On Web, add the ability to query "Light" or "Dark" system theme send `ThemeChanged` on change.
|
||||
- Fix `Event::to_static` returning `None` for user events.
|
||||
|
||||
# 0.21.0 (2020-02-04)
|
||||
|
|
|
@ -101,6 +101,8 @@ features = [
|
|||
'HtmlCanvasElement',
|
||||
'HtmlElement',
|
||||
'KeyboardEvent',
|
||||
'MediaQueryList',
|
||||
'MediaQueryListEvent',
|
||||
'MouseEvent',
|
||||
'Node',
|
||||
'PointerEvent',
|
||||
|
|
|
@ -149,6 +149,9 @@ If your PR makes notable changes to Winit's features, please update this section
|
|||
* Getting the device idiom
|
||||
* Getting the preferred video mode
|
||||
|
||||
### Web
|
||||
* Get if systems preferred color scheme is "dark"
|
||||
|
||||
## Usability
|
||||
* `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial)
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@ use stdweb::web::html_element::CanvasElement;
|
|||
#[cfg(feature = "stdweb")]
|
||||
pub trait WindowExtStdweb {
|
||||
fn canvas(&self) -> CanvasElement;
|
||||
|
||||
/// Whether the browser reports the preferred color scheme to be "dark".
|
||||
fn is_dark_mode(&self) -> bool;
|
||||
}
|
||||
|
||||
#[cfg(feature = "web-sys")]
|
||||
|
@ -22,6 +25,9 @@ use web_sys::HtmlCanvasElement;
|
|||
#[cfg(feature = "web-sys")]
|
||||
pub trait WindowExtWebSys {
|
||||
fn canvas(&self) -> HtmlCanvasElement;
|
||||
|
||||
/// Whether the browser reports the preferred color scheme to be "dark".
|
||||
fn is_dark_mode(&self) -> bool;
|
||||
}
|
||||
|
||||
#[cfg(feature = "stdweb")]
|
||||
|
|
|
@ -2,7 +2,7 @@ use super::{backend, device, proxy::Proxy, runner, window};
|
|||
use crate::dpi::{PhysicalSize, Size};
|
||||
use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent};
|
||||
use crate::event_loop::ControlFlow;
|
||||
use crate::window::WindowId;
|
||||
use crate::window::{Theme, WindowId};
|
||||
use std::clone::Clone;
|
||||
|
||||
pub struct WindowTarget<T: 'static> {
|
||||
|
@ -199,5 +199,18 @@ impl<T> WindowTarget<T> {
|
|||
});
|
||||
runner.request_redraw(WindowId(id));
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_dark_mode(move |is_dark_mode| {
|
||||
let theme = if is_dark_mode {
|
||||
Theme::Dark
|
||||
} else {
|
||||
Theme::Light
|
||||
};
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: WindowId(id),
|
||||
event: WindowEvent::ThemeChanged(theme),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes};
|
|||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use stdweb::js;
|
||||
use stdweb::traits::IPointerEvent;
|
||||
use stdweb::unstable::TryInto;
|
||||
use stdweb::web::event::{
|
||||
|
@ -240,6 +241,22 @@ impl Canvas {
|
|||
self.on_fullscreen_change = Some(self.add_event(move |_: FullscreenChangeEvent| handler()));
|
||||
}
|
||||
|
||||
pub fn on_dark_mode<F>(&mut self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(bool),
|
||||
{
|
||||
// TODO: upstream to stdweb
|
||||
js! {
|
||||
var handler = @{handler};
|
||||
|
||||
if (window.matchMedia) {
|
||||
window.matchMedia("(prefers-color-scheme: dark)").addListener(function(e) {
|
||||
handler(event.matches)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_event<E, F>(&self, mut handler: F) -> EventListenerHandle
|
||||
where
|
||||
E: ConcreteEvent,
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::platform::web::WindowExtStdweb;
|
|||
use crate::window::Window;
|
||||
|
||||
use stdweb::js;
|
||||
use stdweb::unstable::TryInto;
|
||||
use stdweb::web::event::BeforeUnloadEvent;
|
||||
use stdweb::web::window;
|
||||
use stdweb::web::IEventTarget;
|
||||
|
@ -31,6 +32,15 @@ impl WindowExtStdweb for Window {
|
|||
fn canvas(&self) -> CanvasElement {
|
||||
self.window.canvas().raw().clone()
|
||||
}
|
||||
|
||||
fn is_dark_mode(&self) -> bool {
|
||||
// TODO: upstream to stdweb
|
||||
let is_dark_mode = js! {
|
||||
return (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
};
|
||||
|
||||
is_dark_mode.try_into().expect("should return a bool")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window_size() -> LogicalSize<f64> {
|
||||
|
|
|
@ -8,7 +8,10 @@ use std::cell::RefCell;
|
|||
use std::rc::Rc;
|
||||
|
||||
use wasm_bindgen::{closure::Closure, JsCast};
|
||||
use web_sys::{Event, FocusEvent, HtmlCanvasElement, KeyboardEvent, PointerEvent, WheelEvent};
|
||||
use web_sys::{
|
||||
Event, FocusEvent, HtmlCanvasElement, KeyboardEvent, MediaQueryListEvent, PointerEvent,
|
||||
WheelEvent,
|
||||
};
|
||||
|
||||
pub struct Canvas {
|
||||
/// Note: resizing the HTMLCanvasElement should go through `backend::set_canvas_size` to ensure the DPI factor is maintained.
|
||||
|
@ -26,6 +29,7 @@ pub struct Canvas {
|
|||
on_mouse_wheel: Option<Closure<dyn FnMut(WheelEvent)>>,
|
||||
on_fullscreen_change: Option<Closure<dyn FnMut(Event)>>,
|
||||
wants_fullscreen: Rc<RefCell<bool>>,
|
||||
on_dark_mode: Option<Closure<dyn FnMut(MediaQueryListEvent)>>,
|
||||
}
|
||||
|
||||
impl Drop for Canvas {
|
||||
|
@ -77,6 +81,7 @@ impl Canvas {
|
|||
on_mouse_wheel: None,
|
||||
on_fullscreen_change: None,
|
||||
wants_fullscreen: Rc::new(RefCell::new(false)),
|
||||
on_dark_mode: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -251,6 +256,28 @@ impl Canvas {
|
|||
Some(self.add_event("fullscreenchange", move |_: Event| handler()));
|
||||
}
|
||||
|
||||
pub fn on_dark_mode<F>(&mut self, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(bool),
|
||||
{
|
||||
let window = web_sys::window().expect("Failed to obtain window");
|
||||
|
||||
self.on_dark_mode = window
|
||||
.match_media("(prefers-color-scheme: dark)")
|
||||
.ok()
|
||||
.flatten()
|
||||
.and_then(|media| {
|
||||
let closure = Closure::wrap(Box::new(move |event: MediaQueryListEvent| {
|
||||
handler(event.matches())
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
|
||||
media
|
||||
.add_listener_with_opt_callback(Some(&closure.as_ref().unchecked_ref()))
|
||||
.map(|_| closure)
|
||||
.ok()
|
||||
});
|
||||
}
|
||||
|
||||
fn add_event<E, F>(&self, event_name: &str, mut handler: F) -> Closure<dyn FnMut(E)>
|
||||
where
|
||||
E: 'static + AsRef<web_sys::Event> + wasm_bindgen::convert::FromWasmAbi,
|
||||
|
|
|
@ -38,6 +38,17 @@ impl WindowExtWebSys for Window {
|
|||
fn canvas(&self) -> HtmlCanvasElement {
|
||||
self.window.canvas().raw().clone()
|
||||
}
|
||||
|
||||
fn is_dark_mode(&self) -> bool {
|
||||
let window = web_sys::window().expect("Failed to obtain window");
|
||||
|
||||
window
|
||||
.match_media("(prefers-color-scheme: dark)")
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|media| media.matches())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window_size() -> LogicalSize<f64> {
|
||||
|
|
Loading…
Reference in a new issue