servoshell: Upgrade egui and many other dependencies (#31278)

* servoshell: Upgrade `egui` and many other dependencies

This upgrades:
 - `core-graphics`
 - `core-text`
 - `egui` and friends
 - `font-kit`
 - `glow` and friends
 - `harfbuzz-sys`
 - `jni`
 - `nix`
 - `raqote`
 - `raw-window-handle`
 - `winit`

* Downgrade jni until we can properly upgrade

* Update some test results

It's unclear why these are now passing, but they are.

---------

Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Magnus Larsen 2024-05-02 16:21:07 +00:00 committed by GitHub
parent 556bfb7dff
commit 9acf2182cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 796 additions and 560 deletions

605
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -28,5 +28,5 @@ lazy_static = { workspace = true }
mach2 = "0.4" mach2 = "0.4"
[target.'cfg(all(target_os = "linux", not(any(target_arch = "arm", target_arch = "aarch64"))))'.dependencies] [target.'cfg(all(target_os = "linux", not(any(target_arch = "arm", target_arch = "aarch64"))))'.dependencies]
nix = "0.25" nix = { version = "0.27", features = ["signal"] }
unwind-sys = "0.1.4" unwind-sys = "0.1.4"

View file

@ -22,7 +22,7 @@ canvas_traits = { workspace = true }
crossbeam-channel = { workspace = true } crossbeam-channel = { workspace = true }
cssparser = { workspace = true } cssparser = { workspace = true }
euclid = { workspace = true } euclid = { workspace = true }
font-kit = "0.11" font-kit = { version = "0.13" }
fnv = { workspace = true } fnv = { workspace = true }
gfx = { path = "../gfx" } gfx = { path = "../gfx" }
half = "2" half = "2"
@ -32,7 +32,7 @@ lyon_geom = "1.0.4"
num-traits = { workspace = true } num-traits = { workspace = true }
pathfinder_geometry = "0.5" pathfinder_geometry = "0.5"
pixels = { path = "../pixels" } pixels = { path = "../pixels" }
raqote = "0.8.2" raqote = "0.8.4"
servo_arc = { workspace = true } servo_arc = { workspace = true }
sparkle = { workspace = true } sparkle = { workspace = true }
style = { workspace = true } style = { workspace = true }

View file

@ -22,7 +22,7 @@ euclid = { workspace = true }
fnv = { workspace = true } fnv = { workspace = true }
fontsan = { git = "https://github.com/servo/fontsan" } fontsan = { git = "https://github.com/servo/fontsan" }
gfx_traits = { workspace = true } gfx_traits = { workspace = true }
harfbuzz-sys = "0.5" harfbuzz-sys = "0.6"
ipc-channel = { workspace = true } ipc-channel = { workspace = true }
lazy_static = { workspace = true } lazy_static = { workspace = true }
libc = { workspace = true } libc = { workspace = true }
@ -47,19 +47,21 @@ xi-unicode = { workspace = true }
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
byteorder = { workspace = true } byteorder = { workspace = true }
core-foundation = "0.9" core-foundation = "0.9"
core-graphics = "0.22" core-graphics = "0.23"
core-text = "19.0" core-text = "20.1"
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
harfbuzz-sys = { version = "0.6", features = ["bundled"] }
freetype = "0.7" freetype = "0.7"
servo_allocator = { path = "../allocator" } servo_allocator = { path = "../allocator" }
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
fontconfig_sys = { package = "yeslogic-fontconfig-sys", version = "3" } fontconfig_sys = { package = "yeslogic-fontconfig-sys", version = "5" }
[target.'cfg(target_os = "android")'.dependencies] [target.'cfg(target_os = "android")'.dependencies]
xml-rs = "0.8" xml-rs = "0.8"
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
harfbuzz-sys = { version = "0.6", features = ["bundled"] }
dwrote = "0.11" dwrote = "0.11"
truetype = { version = "0.47.3", features = ["ignore-invalid-language-ids"] } truetype = { version = "0.47.3", features = ["ignore-invalid-language-ids"] }

View file

@ -54,29 +54,29 @@ xr-profile = ["libservo/xr-profile"]
servo_allocator = { path = "../../components/allocator" } servo_allocator = { path = "../../components/allocator" }
[target.'cfg(not(target_os = "android"))'.dependencies] [target.'cfg(not(target_os = "android"))'.dependencies]
arboard = "3" arboard = { version = "3" }
backtrace = { workspace = true } backtrace = { workspace = true }
cfg-if = { workspace = true } cfg-if = { workspace = true }
egui = "0.22.0" egui = { version = "0.26.2" }
egui_glow = { version = "0.22.0", features = ["winit"] } egui_glow = { version = "0.26.2", features = ["winit"] }
egui-winit = { version = "0.22.0", default-features = false, features = ["clipboard", "wayland"] } egui-winit = { version = "0.26.2", default-features = false, features = ["clipboard", "wayland"] }
euclid = { workspace = true } euclid = { workspace = true }
getopts = { workspace = true } getopts = { workspace = true }
gilrs = "0.10.7" gilrs = "0.10.7"
gleam = { workspace = true } gleam = { workspace = true }
glow = "0.12.2" glow = "0.13.1"
keyboard-types = { workspace = true } keyboard-types = { workspace = true }
lazy_static = { workspace = true } lazy_static = { workspace = true }
libc = { workspace = true } libc = { workspace = true }
libservo = { path = "../../components/servo" } libservo = { path = "../../components/servo" }
log = { workspace = true } log = { workspace = true }
raw-window-handle = "0.5" raw-window-handle = "0.6"
servo-media = { workspace = true } servo-media = { workspace = true }
shellwords = "1.0.0" shellwords = "1.0.0"
surfman = { workspace = true, features = ["sm-x11", "sm-raw-window-handle"] } surfman = { workspace = true, features = ["sm-x11", "sm-raw-window-handle-06"] }
tinyfiledialogs = "3.0" tinyfiledialogs = "3.0"
webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] } webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] }
winit = "0.28.7" winit = "0.29.10"
url = { workspace = true } url = { workspace = true }
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies] [target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]

View file

@ -63,7 +63,8 @@ impl App {
user_agent: Option<String>, user_agent: Option<String>,
url: Option<String>, url: Option<String>,
) { ) {
let events_loop = EventsLoop::new(opts::get().headless, opts::get().output_file.is_some()); let events_loop = EventsLoop::new(opts::get().headless, opts::get().output_file.is_some())
.expect("Failed to create events loop");
// Implements window methods, used by compositor. // Implements window methods, used by compositor.
let window = if opts::get().headless { let window = if opts::get().headless {
@ -112,13 +113,7 @@ impl App {
debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR); debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR);
app.minibrowser = Some( app.minibrowser = Some(
Minibrowser::new( Minibrowser::new(&rendering_context, &events_loop, initial_url.clone()).into(),
&rendering_context,
&events_loop,
window.as_ref(),
initial_url.clone(),
)
.into(),
); );
} }
@ -200,7 +195,11 @@ impl App {
return; return;
} }
if let winit::event::Event::RedrawRequested(_) = event { if let winit::event::Event::WindowEvent {
window_id: _,
event: winit::event::WindowEvent::RedrawRequested,
} = event
{
// We need to redraw the window for some reason. // We need to redraw the window for some reason.
trace!("RedrawRequested"); trace!("RedrawRequested");
@ -227,7 +226,7 @@ impl App {
event: WindowEvent::ScaleFactorChanged { scale_factor, .. }, event: WindowEvent::ScaleFactorChanged { scale_factor, .. },
.. ..
} => { } => {
// Intercept any ScaleFactorChanged events away from EguiGlow::on_event, so // Intercept any ScaleFactorChanged events away from EguiGlow::on_window_event, so
// we can use our own logic for calculating the scale factor and set eguis // we can use our own logic for calculating the scale factor and set eguis
// scale factor to that value manually. // scale factor to that value manually.
let effective_scale_factor = window.hidpi_factor().get(); let effective_scale_factor = window.hidpi_factor().get();
@ -244,8 +243,12 @@ impl App {
// the minibrowser, and present the new frame. // the minibrowser, and present the new frame.
window.winit_window().unwrap().request_redraw(); window.winit_window().unwrap().request_redraw();
}, },
winit::event::Event::WindowEvent { ref event, .. } => { winit::event::Event::WindowEvent {
let response = minibrowser.on_event(event); ref event,
window_id: _,
} => {
let response =
minibrowser.on_window_event(window.winit_window().unwrap(), &event);
// Update minibrowser if there's resize event to sync up with window. // Update minibrowser if there's resize event to sync up with window.
if let WindowEvent::Resized(_) = event { if let WindowEvent::Resized(_) = event {
minibrowser.update( minibrowser.update(
@ -255,7 +258,6 @@ impl App {
"Sync WebView size with Window Resize event", "Sync WebView size with Window Resize event",
); );
} }
if response.repaint { if response.repaint {
// Request a winit redraw event, so we can recomposite, update and paint // Request a winit redraw event, so we can recomposite, update and paint
// the minibrowser, and present the new frame. // the minibrowser, and present the new frame.
@ -361,7 +363,7 @@ impl App {
/// Processes the given winit Event, possibly converting it to an [EmbedderEvent] and /// Processes the given winit Event, possibly converting it to an [EmbedderEvent] and
/// routing that to the App or relevant Window event queues. /// routing that to the App or relevant Window event queues.
fn queue_embedder_events_for_winit_event(&self, event: winit::event::Event<'_, WakerEvent>) { fn queue_embedder_events_for_winit_event(&self, event: winit::event::Event<WakerEvent>) {
match event { match event {
// App level events // App level events
winit::event::Event::Suspended => { winit::event::Event::Suspended => {
@ -376,10 +378,6 @@ impl App {
}, },
winit::event::Event::DeviceEvent { .. } => {}, winit::event::Event::DeviceEvent { .. } => {},
winit::event::Event::RedrawRequested(_) => {
self.event_queue.borrow_mut().push(EmbedderEvent::Idle);
},
// Window level events // Window level events
winit::event::Event::WindowEvent { winit::event::Event::WindowEvent {
window_id, event, .. window_id, event, ..
@ -388,14 +386,18 @@ impl App {
warn!("Got an event from unknown window"); warn!("Got an event from unknown window");
}, },
Some(window) => { Some(window) => {
if event == winit::event::WindowEvent::RedrawRequested {
self.event_queue.borrow_mut().push(EmbedderEvent::Idle);
}
window.queue_embedder_events_for_winit_event(event); window.queue_embedder_events_for_winit_event(event);
}, },
}, },
winit::event::Event::LoopDestroyed | winit::event::Event::LoopExiting |
winit::event::Event::NewEvents(..) | winit::event::Event::AboutToWait |
winit::event::Event::MainEventsCleared | winit::event::Event::MemoryWarning |
winit::event::Event::RedrawEventsCleared => {}, winit::event::Event::NewEvents(..) => {},
} }
} }

View file

@ -33,6 +33,7 @@
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
use egui::{ViewportId, ViewportOutput};
use egui_glow::ShaderVersion; use egui_glow::ShaderVersion;
pub use egui_winit; pub use egui_winit;
use egui_winit::winit; use egui_winit::winit;
@ -61,17 +62,28 @@ impl EguiGlow {
}) })
.unwrap(); .unwrap();
let egui_ctx = egui::Context::default();
Self { Self {
egui_ctx: Default::default(), egui_winit: egui_winit::State::new(
egui_winit: egui_winit::State::new(event_loop), egui_ctx.clone(),
ViewportId::ROOT,
event_loop,
None,
None,
),
egui_ctx,
painter, painter,
shapes: Default::default(), shapes: Default::default(),
textures_delta: Default::default(), textures_delta: Default::default(),
} }
} }
pub fn on_event(&mut self, event: &winit::event::WindowEvent<'_>) -> EventResponse { pub fn on_window_event(
self.egui_winit.on_event(&self.egui_ctx, event) &mut self,
window: &winit::window::Window,
event: &winit::event::WindowEvent,
) -> EventResponse {
self.egui_winit.on_window_event(window, event)
} }
/// Returns the `Duration` of the timeout after which egui should be repainted even if there's no new events. /// Returns the `Duration` of the timeout after which egui should be repainted even if there's no new events.
@ -85,17 +97,21 @@ impl EguiGlow {
let raw_input = self.egui_winit.take_egui_input(window); let raw_input = self.egui_winit.take_egui_input(window);
let egui::FullOutput { let egui::FullOutput {
platform_output, platform_output,
repaint_after, viewport_output,
textures_delta, textures_delta,
shapes, shapes,
pixels_per_point: _pixels_per_point,
} = self.egui_ctx.run(raw_input, run_ui); } = self.egui_ctx.run(raw_input, run_ui);
self.egui_winit self.egui_winit
.handle_platform_output(window, &self.egui_ctx, platform_output); .handle_platform_output(window, platform_output);
self.shapes = shapes; self.shapes = shapes;
self.textures_delta.append(textures_delta); self.textures_delta.append(textures_delta);
repaint_after match viewport_output.get(&ViewportId::ROOT) {
Some(&ViewportOutput { repaint_delay, .. }) => repaint_delay,
None => std::time::Duration::ZERO,
}
} }
/// Paint the results of the last call to [`Self::run`]. /// Paint the results of the last call to [`Self::run`].
@ -108,14 +124,12 @@ impl EguiGlow {
self.painter.set_texture(id, &image_delta); self.painter.set_texture(id, &image_delta);
} }
let pixels_per_point = self.egui_ctx.pixels_per_point();
/////// let clipped_primitives = self.egui_ctx.tessellate(shapes); /////// let clipped_primitives = self.egui_ctx.tessellate(shapes);
let clipped_primitives = self.egui_ctx.tessellate(shapes.clone()); let clipped_primitives = self.egui_ctx.tessellate(shapes.clone(), pixels_per_point);
let dimensions: [u32; 2] = window.inner_size().into(); let dimensions: [u32; 2] = window.inner_size().into();
self.painter.paint_primitives( self.painter
dimensions, .paint_primitives(dimensions, pixels_per_point, &clipped_primitives);
self.egui_ctx.pixels_per_point(),
&clipped_primitives,
);
for id in textures_delta.free.drain(..) { for id in textures_delta.free.drain(..) {
self.painter.free_texture(id); self.painter.free_texture(id);

View file

@ -33,24 +33,33 @@ impl EventsLoop {
// Ideally, we could use the winit event loop in both modes, // Ideally, we could use the winit event loop in both modes,
// but on Linux, the event loop requires a X11 server. // but on Linux, the event loop requires a X11 server.
#[cfg(not(any(target_os = "linux", target_os = "macos")))] #[cfg(not(any(target_os = "linux", target_os = "macos")))]
pub fn new(_headless: bool, _has_output_file: bool) -> EventsLoop { pub fn new(
EventsLoop(EventLoop::Winit(Some( _headless: bool,
winit::event_loop::EventLoopBuilder::with_user_event().build(), _has_output_file: bool,
))) ) -> Result<EventsLoop, winit::error::EventLoopError> {
Ok(EventsLoop(EventLoop::Winit(Some(
winit::event_loop::EventLoopBuilder::with_user_event().build()?,
))))
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn new(headless: bool, _has_output_file: bool) -> EventsLoop { pub fn new(
EventsLoop(if headless { headless: bool,
_has_output_file: bool,
) -> Result<EventsLoop, winit::error::EventLoopError> {
Ok(EventsLoop(if headless {
EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new()))) EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new())))
} else { } else {
EventLoop::Winit(Some( EventLoop::Winit(Some(
winit::event_loop::EventLoopBuilder::with_user_event().build(), winit::event_loop::EventLoopBuilder::with_user_event().build()?,
)) ))
}) }))
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub fn new(headless: bool, _has_output_file: bool) -> EventsLoop { pub fn new(
EventsLoop(if headless { headless: bool,
_has_output_file: bool,
) -> Result<EventsLoop, winit::error::EventLoopError> {
Ok(EventsLoop(if headless {
EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new()))) EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new())))
} else { } else {
let mut event_loop_builder = winit::event_loop::EventLoopBuilder::with_user_event(); let mut event_loop_builder = winit::event_loop::EventLoopBuilder::with_user_event();
@ -59,8 +68,8 @@ impl EventsLoop {
// when generating an output file. // when generating an output file.
event_loop_builder.with_activation_policy(ActivationPolicy::Prohibited); event_loop_builder.with_activation_policy(ActivationPolicy::Prohibited);
} }
EventLoop::Winit(Some(event_loop_builder.build())) EventLoop::Winit(Some(event_loop_builder.build()?))
}) }))
} }
} }
@ -88,32 +97,36 @@ impl EventsLoop {
pub fn run_forever<F: 'static>(self, mut callback: F) pub fn run_forever<F: 'static>(self, mut callback: F)
where where
F: FnMut( F: FnMut(
winit::event::Event<'_, WakerEvent>, winit::event::Event<WakerEvent>,
Option<&winit::event_loop::EventLoopWindowTarget<WakerEvent>>, Option<&winit::event_loop::EventLoopWindowTarget<WakerEvent>>,
&mut winit::event_loop::ControlFlow, &mut ControlFlow,
), ),
{ {
match self.0 { match self.0 {
EventLoop::Winit(events_loop) => { EventLoop::Winit(events_loop) => {
let events_loop = events_loop.expect("Can't run an unavailable event loop."); let events_loop = events_loop.expect("Can't run an unavailable event loop.");
events_loop.run(move |e, window_target, ref mut control_flow| { events_loop
callback(e, Some(window_target), control_flow) .run(move |e, window_target| {
}); let mut control_flow = ControlFlow::default();
callback(e, Some(window_target), &mut control_flow);
control_flow.apply_to(window_target);
})
.expect("Failed while running events loop");
}, },
EventLoop::Headless(ref data) => { EventLoop::Headless(ref data) => {
let (flag, condvar) = &**data; let (flag, condvar) = &**data;
let mut event = winit::event::Event::NewEvents(winit::event::StartCause::Init); let mut event = winit::event::Event::NewEvents(winit::event::StartCause::Init);
loop { loop {
self.sleep(flag, condvar); self.sleep(flag, condvar);
let mut control_flow = winit::event_loop::ControlFlow::Poll; let mut control_flow = ControlFlow::Poll;
callback(event, None, &mut control_flow); callback(event, None, &mut control_flow);
event = winit::event::Event::<WakerEvent>::UserEvent(WakerEvent); event = winit::event::Event::<WakerEvent>::UserEvent(WakerEvent);
if control_flow != winit::event_loop::ControlFlow::Poll { if control_flow != ControlFlow::Poll {
*flag.lock().unwrap() = false; *flag.lock().unwrap() = false;
} }
if control_flow == winit::event_loop::ControlFlow::Exit { if control_flow == ControlFlow::Exit {
break; break;
} }
} }
@ -136,6 +149,63 @@ impl EventsLoop {
} }
} }
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum ControlFlow {
Poll,
#[default]
Wait,
WaitUntil(std::time::Instant),
/// winit removed their ControlFlow::Exit variant in 0.29.2
Exit,
}
impl ControlFlow {
fn apply_to(self, window_target: &winit::event_loop::EventLoopWindowTarget<WakerEvent>) {
match self {
ControlFlow::Poll => {
window_target.set_control_flow(winit::event_loop::ControlFlow::Poll)
},
ControlFlow::Wait => {
window_target.set_control_flow(winit::event_loop::ControlFlow::Wait)
},
ControlFlow::WaitUntil(instant) => {
window_target.set_control_flow(winit::event_loop::ControlFlow::WaitUntil(instant))
},
ControlFlow::Exit => window_target.exit(),
}
}
pub fn set_poll(&mut self) {
*self = ControlFlow::Poll;
}
pub fn set_wait(&mut self) {
*self = ControlFlow::Wait;
}
#[allow(unused)]
pub fn set_wait_until(&mut self, instant: std::time::Instant) {
*self = ControlFlow::WaitUntil(instant);
}
pub fn set_exit(&mut self) {
*self = ControlFlow::Exit;
}
}
impl From<winit::event_loop::ControlFlow> for ControlFlow {
fn from(cf: winit::event_loop::ControlFlow) -> Self {
match cf {
winit::event_loop::ControlFlow::Poll => Self::Poll,
winit::event_loop::ControlFlow::Wait => Self::Wait,
winit::event_loop::ControlFlow::WaitUntil(instant) => Self::WaitUntil(instant),
}
}
}
struct HeadedEventLoopWaker { struct HeadedEventLoopWaker {
proxy: Arc<Mutex<winit::event_loop::EventLoopProxy<WakerEvent>>>, proxy: Arc<Mutex<winit::event_loop::EventLoopProxy<WakerEvent>>>,
} }

View file

@ -10,7 +10,7 @@ use std::rc::Rc;
use euclid::{Angle, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector2D, Vector3D}; use euclid::{Angle, Length, Point2D, Rotation3D, Scale, Size2D, UnknownUnit, Vector2D, Vector3D};
use log::{debug, info, trace}; use log::{debug, info, trace};
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use servo::compositing::windowing::{ use servo::compositing::windowing::{
AnimationState, EmbedderCoordinates, EmbedderEvent, MouseWindowEvent, WindowMethods, AnimationState, EmbedderCoordinates, EmbedderEvent, MouseWindowEvent, WindowMethods,
}; };
@ -27,10 +27,8 @@ use surfman::{Connection, Context, Device, SurfaceType};
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use winapi; use winapi;
use winit::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; use winit::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
use winit::event::{ use winit::event::{ElementState, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase};
ElementState, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase, use winit::keyboard::{Key as LogicalKey, ModifiersState, NamedKey};
VirtualKeyCode,
};
#[cfg(any(target_os = "linux", target_os = "windows"))] #[cfg(any(target_os = "linux", target_os = "windows"))]
use winit::window::Icon; use winit::window::Icon;
@ -50,10 +48,10 @@ pub struct Window {
primary_monitor: winit::monitor::MonitorHandle, primary_monitor: winit::monitor::MonitorHandle,
event_queue: RefCell<Vec<EmbedderEvent>>, event_queue: RefCell<Vec<EmbedderEvent>>,
mouse_pos: Cell<Point2D<i32, DevicePixel>>, mouse_pos: Cell<Point2D<i32, DevicePixel>>,
last_pressed: Cell<Option<(KeyboardEvent, Option<VirtualKeyCode>)>>, last_pressed: Cell<Option<(KeyboardEvent, Option<LogicalKey>)>>,
/// A map of winit's key codes to key values that are interpreted from /// A map of winit's key codes to key values that are interpreted from
/// winit's ReceivedChar events. /// winit's ReceivedChar events.
keys_down: RefCell<HashMap<VirtualKeyCode, Key>>, keys_down: RefCell<HashMap<LogicalKey, Key>>,
animation_state: Cell<AnimationState>, animation_state: Cell<AnimationState>,
fullscreen: Cell<bool>, fullscreen: Cell<bool>,
device_pixel_ratio_override: Option<f32>, device_pixel_ratio_override: Option<f32>,
@ -119,15 +117,19 @@ impl Window {
let inner_size = winit_size_to_euclid_size(winit_window.inner_size()); let inner_size = winit_size_to_euclid_size(winit_window.inner_size());
// Initialize surfman // Initialize surfman
let display_handle = winit_window.raw_display_handle(); let display_handle = winit_window
let connection = Connection::from_raw_display_handle(display_handle) .display_handle()
.expect("Failed to create connection"); .expect("could not get display handle from window");
let connection =
Connection::from_display_handle(display_handle).expect("Failed to create connection");
let adapter = connection let adapter = connection
.create_adapter() .create_adapter()
.expect("Failed to create adapter"); .expect("Failed to create adapter");
let window_handle = winit_window.raw_window_handle(); let window_handle = winit_window
.window_handle()
.expect("could not get window handle from window");
let native_widget = connection let native_widget = connection
.create_native_widget_from_raw_window_handle(window_handle, Size2D::new(width, height)) .create_native_widget_from_window_handle(window_handle, Size2D::new(width, height))
.expect("Failed to create native widget"); .expect("Failed to create native widget");
let surface_type = SurfaceType::Widget { native_widget }; let surface_type = SurfaceType::Widget { native_widget };
let rendering_context = RenderingContext::create(&connection, &adapter, surface_type) let rendering_context = RenderingContext::create(&connection, &adapter, surface_type)
@ -199,22 +201,27 @@ impl Window {
.push(EmbedderEvent::Keyboard(event)); .push(EmbedderEvent::Keyboard(event));
} }
fn handle_keyboard_input(&self, input: KeyboardInput) { fn handle_keyboard_input(&self, input: KeyEvent) {
let mut event = keyboard_event_from_winit(input, self.modifiers_state.get()); if let Some(input_text) = &input.text {
for ch in input_text.chars() {
self.handle_received_character(ch);
}
}
let mut event = keyboard_event_from_winit(&input, self.modifiers_state.get());
trace!("handling {:?}", event); trace!("handling {:?}", event);
if event.state == KeyState::Down && event.key == Key::Unidentified { if event.state == KeyState::Down && event.key == Key::Unidentified {
// If pressed and probably printable, we expect a ReceivedCharacter event. // If pressed and probably printable, we expect a ReceivedCharacter event.
// Wait for that to be received and don't queue any event right now. // Wait for that to be received and don't queue any event right now.
self.last_pressed.set(Some((event, input.virtual_keycode))); self.last_pressed
.set(Some((event, Some(input.logical_key))));
return; return;
} else if event.state == KeyState::Up && event.key == Key::Unidentified { } else if event.state == KeyState::Up && event.key == Key::Unidentified {
// If release and probably printable, this is following a ReceiverCharacter event. // If release and probably printable, this is following a ReceiverCharacter event.
if let Some(key_code) = input.virtual_keycode { if let Some(key) = self.keys_down.borrow_mut().remove(&input.logical_key) {
if let Some(key) = self.keys_down.borrow_mut().remove(&key_code) {
event.key = key; event.key = key;
} }
} }
}
if event.key != Key::Unidentified { if event.key != Key::Unidentified {
self.last_pressed.set(None); self.last_pressed.set(None);
@ -303,12 +310,21 @@ impl WindowPortsMethods for Window {
self.winit_window.set_title(title); self.winit_window.set_title(title);
} }
fn set_inner_size(&self, size: DeviceIntSize) { fn request_inner_size(&self, size: DeviceIntSize) -> Option<DeviceIntSize> {
let toolbar_height = self.toolbar_height() * self.hidpi_factor(); let toolbar_height = self.toolbar_height() * self.hidpi_factor();
let toolbar_height = toolbar_height.get().ceil() as i32; let toolbar_height = toolbar_height.get().ceil() as i32;
let total_size = PhysicalSize::new(size.width, size.height + toolbar_height); let total_size = PhysicalSize::new(size.width, size.height + toolbar_height);
self.winit_window self.winit_window
.set_inner_size::<PhysicalSize<i32>>(total_size) .request_inner_size::<PhysicalSize<i32>>(PhysicalSize::new(
total_size.width,
total_size.height,
))
.and_then(|size| {
Some(DeviceIntSize::new(
size.width.try_into().ok()?,
size.height.try_into().ok()?,
))
})
} }
fn set_position(&self, point: DeviceIntPoint) { fn set_position(&self, point: DeviceIntPoint) {
@ -338,7 +354,7 @@ impl WindowPortsMethods for Window {
let winit_cursor = match cursor { let winit_cursor = match cursor {
Cursor::Default => CursorIcon::Default, Cursor::Default => CursorIcon::Default,
Cursor::Pointer => CursorIcon::Hand, Cursor::Pointer => CursorIcon::Pointer,
Cursor::ContextMenu => CursorIcon::ContextMenu, Cursor::ContextMenu => CursorIcon::ContextMenu,
Cursor::Help => CursorIcon::Help, Cursor::Help => CursorIcon::Help,
Cursor::Progress => CursorIcon::Progress, Cursor::Progress => CursorIcon::Progress,
@ -384,13 +400,14 @@ impl WindowPortsMethods for Window {
self.winit_window.id() self.winit_window.id()
} }
fn queue_embedder_events_for_winit_event(&self, event: winit::event::WindowEvent<'_>) { fn queue_embedder_events_for_winit_event(&self, event: winit::event::WindowEvent) {
match event { match event {
winit::event::WindowEvent::ReceivedCharacter(ch) => self.handle_received_character(ch), winit::event::WindowEvent::KeyboardInput { event, .. } => {
winit::event::WindowEvent::KeyboardInput { input, .. } => { self.handle_keyboard_input(event)
self.handle_keyboard_input(input) },
winit::event::WindowEvent::ModifiersChanged(modifiers) => {
self.modifiers_state.set(modifiers.state())
}, },
winit::event::WindowEvent::ModifiersChanged(state) => self.modifiers_state.set(state),
winit::event::WindowEvent::MouseInput { state, button, .. } => { winit::event::WindowEvent::MouseInput { state, button, .. } => {
if button == MouseButton::Left || button == MouseButton::Right { if button == MouseButton::Left || button == MouseButton::Right {
self.handle_mouse(button, state, self.mouse_pos.get()); self.handle_mouse(button, state, self.mouse_pos.get());
@ -587,12 +604,15 @@ impl webxr::glwindow::GlWindow for XRWindow {
device: &mut Device, device: &mut Device,
_context: &mut Context, _context: &mut Context,
) -> webxr::glwindow::GlWindowRenderTarget { ) -> webxr::glwindow::GlWindowRenderTarget {
let window_handle = self.winit_window.raw_window_handle(); let window_handle = self
.winit_window
.window_handle()
.expect("could not get window handle from window");
let size = self.winit_window.inner_size(); let size = self.winit_window.inner_size();
let size = Size2D::new(size.width as i32, size.height as i32); let size = Size2D::new(size.width as i32, size.height as i32);
let native_widget = device let native_widget = device
.connection() .connection()
.create_native_widget_from_raw_window_handle(window_handle, size) .create_native_widget_from_window_handle(window_handle, size)
.expect("Failed to create native widget"); .expect("Failed to create native widget");
webxr::glwindow::GlWindowRenderTarget::NativeWidget(native_widget) webxr::glwindow::GlWindowRenderTarget::NativeWidget(native_widget)
} }
@ -648,20 +668,20 @@ impl XRWindowPose {
self.xr_translation.set(vec); self.xr_translation.set(vec);
} }
fn handle_xr_rotation(&self, input: &KeyboardInput, modifiers: ModifiersState) { fn handle_xr_rotation(&self, input: &KeyEvent, modifiers: ModifiersState) {
if input.state != winit::event::ElementState::Pressed { if input.state != winit::event::ElementState::Pressed {
return; return;
} }
let mut x = 0.0; let mut x = 0.0;
let mut y = 0.0; let mut y = 0.0;
match input.virtual_keycode { match input.logical_key {
Some(VirtualKeyCode::Up) => x = 1.0, LogicalKey::Named(NamedKey::ArrowUp) => x = 1.0,
Some(VirtualKeyCode::Down) => x = -1.0, LogicalKey::Named(NamedKey::ArrowDown) => x = -1.0,
Some(VirtualKeyCode::Left) => y = 1.0, LogicalKey::Named(NamedKey::ArrowLeft) => y = 1.0,
Some(VirtualKeyCode::Right) => y = -1.0, LogicalKey::Named(NamedKey::ArrowRight) => y = -1.0,
_ => return, _ => return,
}; };
if modifiers.shift() { if modifiers.shift_key() {
x *= 10.0; x *= 10.0;
y *= 10.0; y *= 10.0;
} }

View file

@ -73,23 +73,27 @@ impl WindowPortsMethods for Window {
unsafe { winit::window::WindowId::dummy() } unsafe { winit::window::WindowId::dummy() }
} }
fn set_inner_size(&self, size: DeviceIntSize) { fn request_inner_size(&self, size: DeviceIntSize) -> Option<DeviceIntSize> {
let (width, height) = size.into(); let (width, height) = size.into();
// Surfman doesn't support zero-sized surfaces. // Surfman doesn't support zero-sized surfaces.
let new_size = Size2D::new(width.max(1), height.max(1)); let new_size = DeviceIntSize::new(width.max(1), height.max(1));
if self.inner_size.get() == new_size { if self.inner_size.get() == new_size.to_untyped() {
return; return Some(new_size);
} }
match self.rendering_context.resize(new_size.to_untyped()) { match self.rendering_context.resize(new_size.to_untyped()) {
Ok(()) => { Ok(()) => {
self.inner_size.set(new_size); self.inner_size.set(new_size.to_untyped());
if let Ok(ref mut queue) = self.event_queue.write() { if let Ok(ref mut queue) = self.event_queue.write() {
queue.push(EmbedderEvent::WindowResize); queue.push(EmbedderEvent::WindowResize);
} }
Some(new_size)
},
Err(error) => {
warn!("Could not resize window: {error:?}");
None
}, },
Err(error) => warn!("Could not resize window: {error:?}"),
} }
} }
@ -126,7 +130,7 @@ impl WindowPortsMethods for Window {
self.animation_state.get() == AnimationState::Animating self.animation_state.get() == AnimationState::Animating
} }
fn queue_embedder_events_for_winit_event(&self, _event: winit::event::WindowEvent<'_>) { fn queue_embedder_events_for_winit_event(&self, _event: winit::event::WindowEvent) {
// Not expecting any winit events. // Not expecting any winit events.
} }

View file

@ -4,7 +4,8 @@
use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers}; use keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
use log::info; use log::info;
use winit::event::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode}; use winit::event::{ElementState, KeyEvent};
use winit::keyboard::{Key as LogicalKey, KeyCode, ModifiersState, NamedKey, PhysicalKey};
// Some shortcuts use Cmd on Mac and Control on other systems. // Some shortcuts use Cmd on Mac and Control on other systems.
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -18,249 +19,249 @@ pub const CMD_OR_ALT: Modifiers = Modifiers::META;
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
pub const CMD_OR_ALT: Modifiers = Modifiers::ALT; pub const CMD_OR_ALT: Modifiers = Modifiers::ALT;
fn get_servo_key_from_winit_key(key: Option<VirtualKeyCode>) -> Key { fn get_servo_key_from_winit_key(key: &LogicalKey) -> Key {
use winit::event::VirtualKeyCode::*;
// TODO: figure out how to map NavigateForward, NavigateBackward // TODO: figure out how to map NavigateForward, NavigateBackward
// TODO: map the remaining keys if possible // TODO: map the remaining keys if possible
let key = if let Some(key) = key {
key
} else {
return Key::Unidentified;
};
match key { match key {
// printable: Key1 to Key0 // printable: Key1 to Key0
// printable: A to Z // printable: A to Z
Escape => Key::Escape, LogicalKey::Named(NamedKey::Escape) => Key::Escape,
F1 => Key::F1, LogicalKey::Named(NamedKey::F1) => Key::F1,
F2 => Key::F2, LogicalKey::Named(NamedKey::F2) => Key::F2,
F3 => Key::F3, LogicalKey::Named(NamedKey::F3) => Key::F3,
F4 => Key::F4, LogicalKey::Named(NamedKey::F4) => Key::F4,
F5 => Key::F5, LogicalKey::Named(NamedKey::F5) => Key::F5,
F6 => Key::F6, LogicalKey::Named(NamedKey::F6) => Key::F6,
F7 => Key::F7, LogicalKey::Named(NamedKey::F7) => Key::F7,
F8 => Key::F8, LogicalKey::Named(NamedKey::F8) => Key::F8,
F9 => Key::F9, LogicalKey::Named(NamedKey::F9) => Key::F9,
F10 => Key::F10, LogicalKey::Named(NamedKey::F10) => Key::F10,
F11 => Key::F11, LogicalKey::Named(NamedKey::F11) => Key::F11,
F12 => Key::F12, LogicalKey::Named(NamedKey::F12) => Key::F12,
// F13 to F15 are not mapped // F13 to F15 are not mapped
Snapshot => Key::PrintScreen, LogicalKey::Named(NamedKey::PrintScreen) => Key::PrintScreen,
// Scroll not mapped // Scroll not mapped
Pause => Key::Pause, LogicalKey::Named(NamedKey::Pause) => Key::Pause,
Insert => Key::Insert, LogicalKey::Named(NamedKey::Insert) => Key::Insert,
Home => Key::Home, LogicalKey::Named(NamedKey::Home) => Key::Home,
Delete => Key::Delete, LogicalKey::Named(NamedKey::Delete) => Key::Delete,
End => Key::End, LogicalKey::Named(NamedKey::End) => Key::End,
PageDown => Key::PageDown, LogicalKey::Named(NamedKey::PageDown) => Key::PageDown,
PageUp => Key::PageUp, LogicalKey::Named(NamedKey::PageUp) => Key::PageUp,
Left => Key::ArrowLeft, LogicalKey::Named(NamedKey::ArrowLeft) => Key::ArrowLeft,
Up => Key::ArrowUp, LogicalKey::Named(NamedKey::ArrowUp) => Key::ArrowUp,
Right => Key::ArrowRight, LogicalKey::Named(NamedKey::ArrowRight) => Key::ArrowRight,
Down => Key::ArrowDown, LogicalKey::Named(NamedKey::ArrowDown) => Key::ArrowDown,
Back => Key::Backspace, LogicalKey::Named(NamedKey::Backspace) => Key::Backspace,
Return => Key::Enter, LogicalKey::Named(NamedKey::Enter) => Key::Enter,
// printable: Space // printable: Space
Compose => Key::Compose, LogicalKey::Named(NamedKey::Compose) => Key::Compose,
// Caret not mapped // Caret not mapped
Numlock => Key::NumLock, LogicalKey::Named(NamedKey::NumLock) => Key::NumLock,
// printable: Numpad0 to Numpad9 // printable: Numpad0 to Numpad9
// AbntC1 and AbntC2 not mapped // AbntC1 and AbntC2 not mapped
// printable: Add, Apostrophe, // printable: Add, Apostrophe,
// Apps, At, Ax not mapped // Apps, At, Ax not mapped
// printable: Backslash, // printable: Backslash,
Calculator => Key::LaunchApplication2, LogicalKey::Named(NamedKey::LaunchApplication2) => Key::LaunchApplication2,
Capital => Key::CapsLock, LogicalKey::Named(NamedKey::CapsLock) => Key::CapsLock,
// printable: Colon, Comma, // printable: Colon, Comma,
Convert => Key::Convert, LogicalKey::Named(NamedKey::Convert) => Key::Convert,
// not mapped: Decimal, // not mapped: Decimal,
// printable: Divide, Equals, Grave, // printable: Divide, Equals, Grave,
Kana => Key::KanaMode, LogicalKey::Named(NamedKey::KanaMode) => Key::KanaMode,
Kanji => Key::KanjiMode, LogicalKey::Named(NamedKey::KanjiMode) => Key::KanjiMode,
LAlt => Key::Alt, LogicalKey::Named(NamedKey::Alt) => Key::Alt,
// printable: LBracket, // printable: LBracket,
LControl => Key::Control, LogicalKey::Named(NamedKey::Control) => Key::Control,
LShift => Key::Shift, LogicalKey::Named(NamedKey::Shift) => Key::Shift,
LWin => Key::Meta, LogicalKey::Named(NamedKey::Meta) => Key::Meta,
Mail => Key::LaunchMail, LogicalKey::Named(NamedKey::LaunchMail) => Key::LaunchMail,
// not mapped: MediaSelect, // not mapped: MediaSelect,
MediaStop => Key::MediaStop, LogicalKey::Named(NamedKey::MediaStop) => Key::MediaStop,
// printable: Minus, Multiply, // printable: Minus, Multiply,
Mute => Key::AudioVolumeMute, LogicalKey::Named(NamedKey::AudioVolumeMute) => Key::AudioVolumeMute,
MyComputer => Key::LaunchApplication1, LogicalKey::Named(NamedKey::LaunchApplication1) => Key::LaunchApplication1,
// not mapped: NavigateForward, NavigateBackward // not mapped: NavigateForward, NavigateBackward
NextTrack => Key::MediaTrackNext, LogicalKey::Named(NamedKey::MediaTrackNext) => Key::MediaTrackNext,
NoConvert => Key::NonConvert, LogicalKey::Named(NamedKey::NonConvert) => Key::NonConvert,
// printable: NumpadComma, NumpadEnter, NumpadEquals, // printable: NumpadComma, NumpadEnter, NumpadEquals,
// not mapped: OEM102, // not mapped: OEM102,
// printable: Period, // printable: Period,
PlayPause => Key::MediaPlayPause, LogicalKey::Named(NamedKey::MediaPlayPause) => Key::MediaPlayPause,
Power => Key::Power, LogicalKey::Named(NamedKey::Power) => Key::Power,
PrevTrack => Key::MediaTrackPrevious, LogicalKey::Named(NamedKey::MediaTrackPrevious) => Key::MediaTrackPrevious,
RAlt => Key::Alt,
// printable RBracket // printable RBracket
RControl => Key::Control,
RShift => Key::Shift,
RWin => Key::Meta,
// printable Semicolon, Slash // printable Semicolon, Slash
Sleep => Key::Standby, LogicalKey::Named(NamedKey::Standby) => Key::Standby,
// not mapped: Stop, // not mapped: Stop,
// printable Subtract, // printable Subtract,
// not mapped: Sysrq, // not mapped: Sysrq,
Tab => Key::Tab, LogicalKey::Named(NamedKey::Tab) => Key::Tab,
// printable: Underline, // printable: Underline,
// not mapped: Unlabeled, // not mapped: Unlabeled,
VolumeDown => Key::AudioVolumeDown, LogicalKey::Named(NamedKey::AudioVolumeDown) => Key::AudioVolumeDown,
VolumeUp => Key::AudioVolumeUp, LogicalKey::Named(NamedKey::AudioVolumeUp) => Key::AudioVolumeUp,
Wake => Key::WakeUp, LogicalKey::Named(NamedKey::WakeUp) => Key::WakeUp,
WebBack => Key::BrowserBack, LogicalKey::Named(NamedKey::BrowserBack) => Key::BrowserBack,
WebFavorites => Key::BrowserFavorites, LogicalKey::Named(NamedKey::BrowserFavorites) => Key::BrowserFavorites,
WebForward => Key::BrowserForward, LogicalKey::Named(NamedKey::BrowserForward) => Key::BrowserForward,
WebHome => Key::BrowserHome, LogicalKey::Named(NamedKey::BrowserHome) => Key::BrowserHome,
WebRefresh => Key::BrowserRefresh, LogicalKey::Named(NamedKey::BrowserRefresh) => Key::BrowserRefresh,
WebSearch => Key::BrowserSearch, LogicalKey::Named(NamedKey::BrowserSearch) => Key::BrowserSearch,
WebStop => Key::BrowserStop, LogicalKey::Named(NamedKey::BrowserStop) => Key::BrowserStop,
// printable Yen, // printable Yen,
Copy => Key::Copy, LogicalKey::Named(NamedKey::Copy) => Key::Copy,
Paste => Key::Paste, LogicalKey::Named(NamedKey::Paste) => Key::Paste,
Cut => Key::Cut, LogicalKey::Named(NamedKey::Cut) => Key::Cut,
_ => Key::Unidentified, _ => Key::Unidentified,
} }
} }
fn get_servo_location_from_winit_key(key: Option<VirtualKeyCode>) -> Location { fn get_servo_location_from_physical_key(physical_key: PhysicalKey) -> Location {
use winit::event::VirtualKeyCode::*; let key_code = if let PhysicalKey::Code(key_code) = physical_key {
// TODO: add more numpad keys key_code
let key = if let Some(key) = key {
key
} else { } else {
return Location::Standard; return Location::Standard;
}; };
match key {
LShift | LControl | LAlt | LWin => Location::Left, // TODO: add more numpad keys
RShift | RControl | RAlt | RWin => Location::Right, match key_code {
Numpad0 | Numpad1 | Numpad2 | Numpad3 | Numpad4 | Numpad5 | Numpad6 | Numpad7 | KeyCode::ShiftLeft | KeyCode::ControlLeft | KeyCode::AltLeft | KeyCode::SuperLeft => {
Numpad8 | Numpad9 => Location::Numpad, Location::Left
NumpadComma | NumpadEnter | NumpadEquals => Location::Numpad, },
KeyCode::ShiftRight | KeyCode::ControlRight | KeyCode::AltRight | KeyCode::SuperRight => {
Location::Right
},
KeyCode::Numpad0 |
KeyCode::Numpad1 |
KeyCode::Numpad2 |
KeyCode::Numpad3 |
KeyCode::Numpad4 |
KeyCode::Numpad5 |
KeyCode::Numpad6 |
KeyCode::Numpad7 |
KeyCode::Numpad8 |
KeyCode::Numpad9 => Location::Numpad,
KeyCode::NumpadComma | KeyCode::NumpadEnter | KeyCode::NumpadEqual => Location::Numpad,
_ => Location::Standard, _ => Location::Standard,
} }
} }
#[cfg(target_os = "linux")] fn get_servo_code_from_physical_key(physical_key: PhysicalKey) -> Code {
fn get_servo_code_from_scancode(scancode: u32) -> Code { let key_code = if let PhysicalKey::Code(key_code) = physical_key {
key_code
} else {
return Code::Unidentified;
};
// TODO: Map more codes // TODO: Map more codes
use keyboard_types::Code::*; match key_code {
match scancode { KeyCode::Escape => Code::Escape,
1 => Escape, KeyCode::Digit1 => Code::Digit1,
2 => Digit1, KeyCode::Digit2 => Code::Digit2,
3 => Digit2, KeyCode::Digit3 => Code::Digit3,
4 => Digit3, KeyCode::Digit4 => Code::Digit4,
5 => Digit4, KeyCode::Digit5 => Code::Digit5,
6 => Digit5, KeyCode::Digit6 => Code::Digit6,
7 => Digit6, KeyCode::Digit7 => Code::Digit7,
8 => Digit7, KeyCode::Digit8 => Code::Digit8,
9 => Digit8, KeyCode::Digit9 => Code::Digit9,
10 => Digit9, KeyCode::Digit0 => Code::Digit0,
11 => Digit0,
14 => Backspace, KeyCode::Backspace => Code::Backspace,
15 => Tab, KeyCode::Tab => Code::Tab,
16 => KeyQ, KeyCode::KeyQ => Code::KeyQ,
17 => KeyW, KeyCode::KeyW => Code::KeyW,
18 => KeyE, KeyCode::KeyE => Code::KeyE,
19 => KeyR, KeyCode::KeyR => Code::KeyR,
20 => KeyT, KeyCode::KeyT => Code::KeyT,
21 => KeyY, KeyCode::KeyY => Code::KeyY,
22 => KeyU, KeyCode::KeyU => Code::KeyU,
23 => KeyI, KeyCode::KeyI => Code::KeyI,
24 => KeyO, KeyCode::KeyO => Code::KeyO,
25 => KeyP, KeyCode::KeyP => Code::KeyP,
26 => BracketLeft, KeyCode::BracketLeft => Code::BracketLeft,
27 => BracketRight, KeyCode::BracketRight => Code::BracketRight,
28 => Enter, KeyCode::Enter => Code::Enter,
30 => KeyA, KeyCode::KeyA => Code::KeyA,
31 => KeyS, KeyCode::KeyS => Code::KeyS,
32 => KeyD, KeyCode::KeyD => Code::KeyD,
33 => KeyF, KeyCode::KeyF => Code::KeyF,
34 => KeyG, KeyCode::KeyG => Code::KeyG,
35 => KeyH, KeyCode::KeyH => Code::KeyH,
36 => KeyJ, KeyCode::KeyJ => Code::KeyJ,
37 => KeyK, KeyCode::KeyK => Code::KeyK,
38 => KeyL, KeyCode::KeyL => Code::KeyL,
39 => Semicolon, KeyCode::Semicolon => Code::Semicolon,
40 => Quote, KeyCode::Quote => Code::Quote,
42 => ShiftLeft, KeyCode::ShiftLeft => Code::ShiftLeft,
43 => Backslash, KeyCode::Backslash => Code::Backslash,
44 => KeyZ, KeyCode::KeyZ => Code::KeyZ,
45 => KeyX, KeyCode::KeyX => Code::KeyX,
46 => KeyC, KeyCode::KeyC => Code::KeyC,
47 => KeyV, KeyCode::KeyV => Code::KeyV,
48 => KeyB, KeyCode::KeyB => Code::KeyB,
49 => KeyN, KeyCode::KeyN => Code::KeyN,
50 => KeyM, KeyCode::KeyM => Code::KeyM,
51 => Comma, KeyCode::Comma => Code::Comma,
52 => Period, KeyCode::Period => Code::Period,
53 => Slash, KeyCode::Slash => Code::Slash,
54 => ShiftRight, KeyCode::ShiftRight => Code::ShiftRight,
57 => Space, KeyCode::Space => Code::Space,
59 => F1, KeyCode::F1 => Code::F1,
60 => F2, KeyCode::F2 => Code::F2,
61 => F3, KeyCode::F3 => Code::F3,
62 => F4, KeyCode::F4 => Code::F4,
63 => F5, KeyCode::F5 => Code::F5,
64 => F6, KeyCode::F6 => Code::F6,
65 => F7, KeyCode::F7 => Code::F7,
66 => F8, KeyCode::F8 => Code::F8,
67 => F9, KeyCode::F9 => Code::F9,
68 => F10, KeyCode::F10 => Code::F10,
87 => F11, KeyCode::F11 => Code::F11,
88 => F12, KeyCode::F12 => Code::F12,
103 => ArrowUp, KeyCode::ArrowUp => Code::ArrowUp,
104 => PageUp, KeyCode::PageUp => Code::PageUp,
105 => ArrowLeft, KeyCode::ArrowLeft => Code::ArrowLeft,
106 => ArrowRight, KeyCode::ArrowRight => Code::ArrowRight,
102 => Home, KeyCode::Home => Code::Home,
107 => End, KeyCode::End => Code::End,
108 => ArrowDown, KeyCode::ArrowDown => Code::ArrowDown,
109 => PageDown, KeyCode::PageDown => Code::PageDown,
110 => Insert, KeyCode::Insert => Code::Insert,
111 => Delete, KeyCode::Delete => Code::Delete,
_ => Unidentified, _ => Code::Unidentified,
} }
} }
#[cfg(not(target_os = "linux"))]
fn get_servo_code_from_scancode(_scancode: u32) -> Code {
// TODO: Implement for Windows and Mac OS
Code::Unidentified
}
fn get_modifiers(mods: ModifiersState) -> Modifiers { fn get_modifiers(mods: ModifiersState) -> Modifiers {
let mut modifiers = Modifiers::empty(); let mut modifiers = Modifiers::empty();
modifiers.set(Modifiers::CONTROL, mods.ctrl()); modifiers.set(Modifiers::CONTROL, mods.control_key());
modifiers.set(Modifiers::SHIFT, mods.shift()); modifiers.set(Modifiers::SHIFT, mods.shift_key());
modifiers.set(Modifiers::ALT, mods.alt()); modifiers.set(Modifiers::ALT, mods.alt_key());
modifiers.set(Modifiers::META, mods.logo()); modifiers.set(Modifiers::META, mods.super_key());
modifiers modifiers
} }
pub fn keyboard_event_from_winit(input: KeyboardInput, state: ModifiersState) -> KeyboardEvent { pub fn keyboard_event_from_winit(input: &KeyEvent, state: ModifiersState) -> KeyboardEvent {
info!("winit keyboard input: {:?}", input); info!("winit keyboard input: {:?}", input);
KeyboardEvent { KeyboardEvent {
state: match input.state { state: match input.state {
ElementState::Pressed => KeyState::Down, ElementState::Pressed => KeyState::Down,
ElementState::Released => KeyState::Up, ElementState::Released => KeyState::Up,
}, },
key: get_servo_key_from_winit_key(input.virtual_keycode), key: get_servo_key_from_winit_key(&input.logical_key),
code: get_servo_code_from_scancode(input.scancode), code: get_servo_code_from_physical_key(input.physical_key),
location: get_servo_location_from_winit_key(input.virtual_keycode), location: get_servo_location_from_physical_key(input.physical_key),
modifiers: get_modifiers(state), modifiers: get_modifiers(state),
repeat: false, repeat: false,
is_composing: false, is_composing: false,

View file

@ -61,7 +61,6 @@ impl Minibrowser {
pub fn new( pub fn new(
rendering_context: &RenderingContext, rendering_context: &RenderingContext,
events_loop: &EventsLoop, events_loop: &EventsLoop,
window: &dyn WindowPortsMethods,
initial_url: ServoUrl, initial_url: ServoUrl,
) -> Self { ) -> Self {
let gl = unsafe { let gl = unsafe {
@ -70,10 +69,6 @@ impl Minibrowser {
// Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs
let context = EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None); let context = EguiGlow::new(events_loop.as_winit(), Arc::new(gl), None);
context
.egui_ctx
.set_pixels_per_point(window.hidpi_factor().get());
let widget_surface_fbo = match rendering_context.context_surface_info() { let widget_surface_fbo = match rendering_context.context_surface_info() {
Ok(Some(info)) => NonZeroU32::new(info.framebuffer_object).map(NativeFramebuffer), Ok(Some(info)) => NonZeroU32::new(info.framebuffer_object).map(NativeFramebuffer),
Ok(None) => panic!("Failed to get widget surface info from surfman!"), Ok(None) => panic!("Failed to get widget surface info from surfman!"),
@ -96,8 +91,12 @@ impl Minibrowser {
/// Preprocess the given [winit::event::WindowEvent], returning unconsumed for mouse events in /// Preprocess the given [winit::event::WindowEvent], returning unconsumed for mouse events in
/// the Servo browser rect. This is needed because the CentralPanel we create for our webview /// the Servo browser rect. This is needed because the CentralPanel we create for our webview
/// would otherwise make egui report events in that area as consumed. /// would otherwise make egui report events in that area as consumed.
pub fn on_event(&mut self, event: &winit::event::WindowEvent<'_>) -> EventResponse { pub fn on_window_event(
let mut result = self.context.on_event(event); &mut self,
window: &winit::window::Window,
event: &winit::event::WindowEvent,
) -> EventResponse {
let mut result = self.context.on_window_event(window, event);
result.consumed &= match event { result.consumed &= match event {
winit::event::WindowEvent::CursorMoved { position, .. } => { winit::event::WindowEvent::CursorMoved { position, .. } => {
let scale = Scale::<_, DeviceIndependentPixel, _>::new( let scale = Scale::<_, DeviceIndependentPixel, _>::new(

View file

@ -65,7 +65,7 @@ mod from_winit {
}; };
} }
impl LogTarget for winit::event::Event<'_, WakerEvent> { impl LogTarget for winit::event::Event<WakerEvent> {
fn log_target(&self) -> &'static str { fn log_target(&self) -> &'static str {
use winit::event::StartCause; use winit::event::StartCause;
match self { match self {
@ -80,15 +80,14 @@ mod from_winit {
Self::UserEvent(WakerEvent) => target!("UserEvent(WakerEvent)"), Self::UserEvent(WakerEvent) => target!("UserEvent(WakerEvent)"),
Self::Suspended => target!("Suspended"), Self::Suspended => target!("Suspended"),
Self::Resumed => target!("Resumed"), Self::Resumed => target!("Resumed"),
Self::MainEventsCleared => target!("MainEventsCleared"), Self::AboutToWait => target!("AboutToWait"),
Self::RedrawRequested(..) => target!("RedrawRequested"), Self::LoopExiting => target!("LoopExiting"),
Self::RedrawEventsCleared => target!("RedrawEventsCleared"), Self::MemoryWarning => target!("MemoryWarning"),
Self::LoopDestroyed => target!("LoopDestroyed"),
} }
} }
} }
impl LogTarget for winit::event::WindowEvent<'_> { impl LogTarget for winit::event::WindowEvent {
fn log_target(&self) -> &'static str { fn log_target(&self) -> &'static str {
macro_rules! target_variant { macro_rules! target_variant {
($name:literal) => { ($name:literal) => {
@ -96,6 +95,7 @@ mod from_winit {
}; };
} }
match self { match self {
Self::ActivationTokenDone { .. } => target!("ActivationTokenDone"),
Self::Resized(..) => target_variant!("Resized"), Self::Resized(..) => target_variant!("Resized"),
Self::Moved(..) => target_variant!("Moved"), Self::Moved(..) => target_variant!("Moved"),
Self::CloseRequested => target_variant!("CloseRequested"), Self::CloseRequested => target_variant!("CloseRequested"),
@ -103,7 +103,6 @@ mod from_winit {
Self::DroppedFile(..) => target_variant!("DroppedFile"), Self::DroppedFile(..) => target_variant!("DroppedFile"),
Self::HoveredFile(..) => target_variant!("HoveredFile"), Self::HoveredFile(..) => target_variant!("HoveredFile"),
Self::HoveredFileCancelled => target_variant!("HoveredFileCancelled"), Self::HoveredFileCancelled => target_variant!("HoveredFileCancelled"),
Self::ReceivedCharacter(..) => target_variant!("ReceivedCharacter"),
Self::Focused(..) => target_variant!("Focused"), Self::Focused(..) => target_variant!("Focused"),
Self::KeyboardInput { .. } => target_variant!("KeyboardInput"), Self::KeyboardInput { .. } => target_variant!("KeyboardInput"),
Self::ModifiersChanged(..) => target_variant!("ModifiersChanged"), Self::ModifiersChanged(..) => target_variant!("ModifiersChanged"),
@ -122,6 +121,7 @@ mod from_winit {
Self::ScaleFactorChanged { .. } => target_variant!("ScaleFactorChanged"), Self::ScaleFactorChanged { .. } => target_variant!("ScaleFactorChanged"),
Self::ThemeChanged(..) => target_variant!("ThemeChanged"), Self::ThemeChanged(..) => target_variant!("ThemeChanged"),
Self::Occluded(..) => target_variant!("Occluded"), Self::Occluded(..) => target_variant!("Occluded"),
Self::RedrawRequested => target!("RedrawRequested"),
} }
} }
} }

View file

@ -477,7 +477,7 @@ where
.push(EmbedderEvent::MoveResizeWebView(webview_id, new_rect)); .push(EmbedderEvent::MoveResizeWebView(webview_id, new_rect));
} }
} }
self.window.set_inner_size(size); self.window.request_inner_size(size);
}, },
EmbedderMsg::Prompt(definition, origin) => { EmbedderMsg::Prompt(definition, origin) => {
let res = if opts::get().headless { let res = if opts::get().headless {

View file

@ -34,10 +34,10 @@ pub trait WindowPortsMethods: WindowMethods {
) -> Option<Scale<f32, DeviceIndependentPixel, DevicePixel>>; ) -> Option<Scale<f32, DeviceIndependentPixel, DevicePixel>>;
fn page_height(&self) -> f32; fn page_height(&self) -> f32;
fn get_fullscreen(&self) -> bool; fn get_fullscreen(&self) -> bool;
fn queue_embedder_events_for_winit_event(&self, event: winit::event::WindowEvent<'_>); fn queue_embedder_events_for_winit_event(&self, event: winit::event::WindowEvent);
fn is_animating(&self) -> bool; fn is_animating(&self) -> bool;
fn set_title(&self, _title: &str) {} fn set_title(&self, _title: &str) {}
fn set_inner_size(&self, _size: DeviceIntSize); fn request_inner_size(&self, size: DeviceIntSize) -> Option<DeviceIntSize>;
fn set_position(&self, _point: DeviceIntPoint) {} fn set_position(&self, _point: DeviceIntPoint) {}
fn set_fullscreen(&self, _state: bool) {} fn set_fullscreen(&self, _state: bool) {}
fn set_cursor(&self, _cursor: Cursor) {} fn set_cursor(&self, _cursor: Cursor) {}

View file

@ -486,11 +486,6 @@ class CommandBase(object):
if platform.is_macos: if platform.is_macos:
util.prepend_paths_to_env(env, "DYLD_LIBRARY_PATH", os.path.join(gstreamer_root, "lib")) util.prepend_paths_to_env(env, "DYLD_LIBRARY_PATH", os.path.join(gstreamer_root, "lib"))
effective_target = self.cross_compile_target or servo.platform.host_triple()
if "msvc" in effective_target:
# Always build harfbuzz from source
env["HARFBUZZ_SYS_NO_PKG_CONFIG"] = "true"
if sys.platform != "win32": if sys.platform != "win32":
env.setdefault("CC", "clang") env.setdefault("CC", "clang")
env.setdefault("CXX", "clang++") env.setdefault("CXX", "clang++")
@ -615,7 +610,6 @@ class CommandBase(object):
env['OBJCOPY'] = to_ndk_bin("llvm-objcopy") env['OBJCOPY'] = to_ndk_bin("llvm-objcopy")
env['YASM'] = to_ndk_bin("yasm") env['YASM'] = to_ndk_bin("yasm")
env['STRIP'] = to_ndk_bin("llvm-strip") env['STRIP'] = to_ndk_bin("llvm-strip")
env['HARFBUZZ_SYS_NO_PKG_CONFIG'] = "true"
env['RUST_FONTCONFIG_DLOPEN'] = "on" env['RUST_FONTCONFIG_DLOPEN'] = "on"
env["LIBCLANG_PATH"] = path.join(llvm_toolchain, "lib64") env["LIBCLANG_PATH"] = path.join(llvm_toolchain, "lib64")

View file

@ -38,7 +38,7 @@ APT_PKGS = [
'libharfbuzz-dev', 'liblzma-dev', 'libudev-dev', 'libunwind-dev', 'libharfbuzz-dev', 'liblzma-dev', 'libudev-dev', 'libunwind-dev',
'libvulkan1', 'libx11-dev', 'libxcb-render0-dev', 'libxcb-shape0-dev', 'libvulkan1', 'libx11-dev', 'libxcb-render0-dev', 'libxcb-shape0-dev',
'libxcb-xfixes0-dev', 'libxmu-dev', 'libxmu6', 'libegl1-mesa-dev', 'libxcb-xfixes0-dev', 'libxmu-dev', 'libxmu6', 'libegl1-mesa-dev',
'llvm-dev', 'm4', 'xorg-dev', 'llvm-dev', 'm4', 'xorg-dev', 'libxkbcommon0', "libxkbcommon-x11-0"
] ]
# https://packages.fedoraproject.org # https://packages.fedoraproject.org
@ -56,7 +56,8 @@ DNF_PKGS = ['libtool', 'gcc-c++', 'libXi-devel', 'freetype-devel',
'gstreamer1-devel', 'gstreamer1-plugins-base-devel', 'gstreamer1-devel', 'gstreamer1-plugins-base-devel',
'gstreamer1-plugins-good', 'gstreamer1-plugins-bad-free-devel', 'gstreamer1-plugins-good', 'gstreamer1-plugins-bad-free-devel',
'gstreamer1-plugins-ugly-free', 'libjpeg-turbo-devel', 'gstreamer1-plugins-ugly-free', 'libjpeg-turbo-devel',
'zlib', 'libjpeg', 'vulkan-loader'] 'zlib', 'libjpeg', 'vulkan-loader', 'libxkbcommon',
'libxkbcommon-x11']
# https://voidlinux.org/packages/ # https://voidlinux.org/packages/
# 1. open devtools # 1. open devtools
@ -71,7 +72,8 @@ XBPS_PKGS = ['libtool', 'gcc', 'libXi-devel', 'freetype-devel',
'ncurses-devel', 'harfbuzz-devel', 'ccache', 'glu-devel', 'ncurses-devel', 'harfbuzz-devel', 'ccache', 'glu-devel',
'clang', 'gstreamer1-devel', 'gst-plugins-base1-devel', 'clang', 'gstreamer1-devel', 'gst-plugins-base1-devel',
'gst-plugins-good1', 'gst-plugins-bad1-devel', 'gst-plugins-good1', 'gst-plugins-bad1-devel',
'gst-plugins-ugly1', 'vulkan-loader'] 'gst-plugins-ugly1', 'vulkan-loader', 'libxkbcommon',
'libxkbcommon-x11']
GSTREAMER_URL = \ GSTREAMER_URL = \
"https://github.com/servo/servo-build-deps/releases/download/linux/gstreamer-1.16-x86_64-linux-gnu.20190515.tar.gz" "https://github.com/servo/servo-build-deps/releases/download/linux/gstreamer-1.16-x86_64-linux-gnu.20190515.tar.gz"

View file

@ -34,10 +34,10 @@ packages = [
# New versions of these dependencies is pulled in by GStreamer / GLib. # New versions of these dependencies is pulled in by GStreamer / GLib.
"itertools", "itertools",
"proc-macro-crate",
"toml", "toml",
# Duplicated by winit. # Duplicated by winit.
"jni",
"windows-sys", "windows-sys",
"windows-targets", "windows-targets",
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm",
@ -52,7 +52,6 @@ packages = [
"foreign-types", "foreign-types",
"foreign-types-shared", "foreign-types-shared",
"metal", "metal",
"raw-window-handle",
# Duplicated by indexmap. # Duplicated by indexmap.
"hashbrown", "hashbrown",
@ -68,10 +67,6 @@ packages = [
"phf", "phf",
"phf_generator", "phf_generator",
"phf_shared", "phf_shared",
# These can be removed once winit, font-kit, etc are upgraded
"core-graphics",
"core-text",
] ]
# Files that are ignored for all tidy and lint checks. # Files that are ignored for all tidy and lint checks.
files = [ files = [

View file

@ -1,2 +0,0 @@
[shaping-023-ref.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[shaping-023-ref.html]
expected: FAIL