mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +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.
|
- On Wayland, fix color from `close_button_icon_color` not applying.
|
||||||
- Ignore locale if unsupported by X11 backend
|
- Ignore locale if unsupported by X11 backend
|
||||||
- On Wayland, Add HiDPI cursor support
|
- 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.
|
- Fix `Event::to_static` returning `None` for user events.
|
||||||
|
|
||||||
# 0.21.0 (2020-02-04)
|
# 0.21.0 (2020-02-04)
|
||||||
|
|
|
@ -101,6 +101,8 @@ features = [
|
||||||
'HtmlCanvasElement',
|
'HtmlCanvasElement',
|
||||||
'HtmlElement',
|
'HtmlElement',
|
||||||
'KeyboardEvent',
|
'KeyboardEvent',
|
||||||
|
'MediaQueryList',
|
||||||
|
'MediaQueryListEvent',
|
||||||
'MouseEvent',
|
'MouseEvent',
|
||||||
'Node',
|
'Node',
|
||||||
'PointerEvent',
|
'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 device idiom
|
||||||
* Getting the preferred video mode
|
* Getting the preferred video mode
|
||||||
|
|
||||||
|
### Web
|
||||||
|
* Get if systems preferred color scheme is "dark"
|
||||||
|
|
||||||
## Usability
|
## Usability
|
||||||
* `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial)
|
* `serde`: Enables serialization/deserialization of certain types with Serde. (Maintainer: @Osspial)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,9 @@ use stdweb::web::html_element::CanvasElement;
|
||||||
#[cfg(feature = "stdweb")]
|
#[cfg(feature = "stdweb")]
|
||||||
pub trait WindowExtStdweb {
|
pub trait WindowExtStdweb {
|
||||||
fn canvas(&self) -> CanvasElement;
|
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")]
|
#[cfg(feature = "web-sys")]
|
||||||
|
@ -22,6 +25,9 @@ use web_sys::HtmlCanvasElement;
|
||||||
#[cfg(feature = "web-sys")]
|
#[cfg(feature = "web-sys")]
|
||||||
pub trait WindowExtWebSys {
|
pub trait WindowExtWebSys {
|
||||||
fn canvas(&self) -> HtmlCanvasElement;
|
fn canvas(&self) -> HtmlCanvasElement;
|
||||||
|
|
||||||
|
/// Whether the browser reports the preferred color scheme to be "dark".
|
||||||
|
fn is_dark_mode(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "stdweb")]
|
#[cfg(feature = "stdweb")]
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::{backend, device, proxy::Proxy, runner, window};
|
||||||
use crate::dpi::{PhysicalSize, Size};
|
use crate::dpi::{PhysicalSize, Size};
|
||||||
use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent};
|
use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent};
|
||||||
use crate::event_loop::ControlFlow;
|
use crate::event_loop::ControlFlow;
|
||||||
use crate::window::WindowId;
|
use crate::window::{Theme, WindowId};
|
||||||
use std::clone::Clone;
|
use std::clone::Clone;
|
||||||
|
|
||||||
pub struct WindowTarget<T: 'static> {
|
pub struct WindowTarget<T: 'static> {
|
||||||
|
@ -199,5 +199,18 @@ impl<T> WindowTarget<T> {
|
||||||
});
|
});
|
||||||
runner.request_redraw(WindowId(id));
|
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::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use stdweb::js;
|
||||||
use stdweb::traits::IPointerEvent;
|
use stdweb::traits::IPointerEvent;
|
||||||
use stdweb::unstable::TryInto;
|
use stdweb::unstable::TryInto;
|
||||||
use stdweb::web::event::{
|
use stdweb::web::event::{
|
||||||
|
@ -240,6 +241,22 @@ impl Canvas {
|
||||||
self.on_fullscreen_change = Some(self.add_event(move |_: FullscreenChangeEvent| handler()));
|
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
|
fn add_event<E, F>(&self, mut handler: F) -> EventListenerHandle
|
||||||
where
|
where
|
||||||
E: ConcreteEvent,
|
E: ConcreteEvent,
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::platform::web::WindowExtStdweb;
|
||||||
use crate::window::Window;
|
use crate::window::Window;
|
||||||
|
|
||||||
use stdweb::js;
|
use stdweb::js;
|
||||||
|
use stdweb::unstable::TryInto;
|
||||||
use stdweb::web::event::BeforeUnloadEvent;
|
use stdweb::web::event::BeforeUnloadEvent;
|
||||||
use stdweb::web::window;
|
use stdweb::web::window;
|
||||||
use stdweb::web::IEventTarget;
|
use stdweb::web::IEventTarget;
|
||||||
|
@ -31,6 +32,15 @@ impl WindowExtStdweb for Window {
|
||||||
fn canvas(&self) -> CanvasElement {
|
fn canvas(&self) -> CanvasElement {
|
||||||
self.window.canvas().raw().clone()
|
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> {
|
pub fn window_size() -> LogicalSize<f64> {
|
||||||
|
|
|
@ -8,7 +8,10 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use wasm_bindgen::{closure::Closure, JsCast};
|
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 {
|
pub struct Canvas {
|
||||||
/// Note: resizing the HTMLCanvasElement should go through `backend::set_canvas_size` to ensure the DPI factor is maintained.
|
/// 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_mouse_wheel: Option<Closure<dyn FnMut(WheelEvent)>>,
|
||||||
on_fullscreen_change: Option<Closure<dyn FnMut(Event)>>,
|
on_fullscreen_change: Option<Closure<dyn FnMut(Event)>>,
|
||||||
wants_fullscreen: Rc<RefCell<bool>>,
|
wants_fullscreen: Rc<RefCell<bool>>,
|
||||||
|
on_dark_mode: Option<Closure<dyn FnMut(MediaQueryListEvent)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Canvas {
|
impl Drop for Canvas {
|
||||||
|
@ -77,6 +81,7 @@ impl Canvas {
|
||||||
on_mouse_wheel: None,
|
on_mouse_wheel: None,
|
||||||
on_fullscreen_change: None,
|
on_fullscreen_change: None,
|
||||||
wants_fullscreen: Rc::new(RefCell::new(false)),
|
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()));
|
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)>
|
fn add_event<E, F>(&self, event_name: &str, mut handler: F) -> Closure<dyn FnMut(E)>
|
||||||
where
|
where
|
||||||
E: 'static + AsRef<web_sys::Event> + wasm_bindgen::convert::FromWasmAbi,
|
E: 'static + AsRef<web_sys::Event> + wasm_bindgen::convert::FromWasmAbi,
|
||||||
|
|
|
@ -38,6 +38,17 @@ impl WindowExtWebSys for Window {
|
||||||
fn canvas(&self) -> HtmlCanvasElement {
|
fn canvas(&self) -> HtmlCanvasElement {
|
||||||
self.window.canvas().raw().clone()
|
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> {
|
pub fn window_size() -> LogicalSize<f64> {
|
||||||
|
|
Loading…
Reference in a new issue