Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: smooth resizing #221

Merged
merged 9 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,8 @@ impl IOCompositor {
self.pending_paint_metrics.insert(pipeline_id, epoch);
}

CompositorMsg::CrossProcess(cross_proces_message) => {
self.handle_cross_process_message(cross_proces_message);
CompositorMsg::CrossProcess(cross_process_message) => {
self.handle_cross_process_message(cross_process_message);
}
}

Expand Down
14 changes: 3 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,12 @@ impl ApplicationHandler<EventLoopProxyMessage> for App {

fn window_event(
&mut self,
_event_loop: &winit::event_loop::ActiveEventLoop,
event_loop: &winit::event_loop::ActiveEventLoop,
window_id: winit::window::WindowId,
event: winit::event::WindowEvent,
) {
if let Some(v) = self.verso.as_mut() {
v.handle_winit_window_event(window_id, event);
// XXX: Windows seems to be able to handle servo directly.
// We can think about how to handle all platforms the same way in the future.
#[cfg(windows)]
v.handle_servo_messages(_event_loop);
#[cfg(not(windows))]
if let Err(e) = self.proxy.send_event(EventLoopProxyMessage::Wake) {
log::error!("Failed to send wake message to Verso: {e}");
}
v.handle_window_event(event_loop, window_id, event);
}
}

Expand All @@ -46,7 +38,7 @@ impl ApplicationHandler<EventLoopProxyMessage> for App {
if let Some(v) = self.verso.as_mut() {
match event {
EventLoopProxyMessage::Wake => {
v.handle_servo_messages(event_loop);
v.request_redraw(event_loop);
}
EventLoopProxyMessage::IpcMessage(message) => {
v.handle_incoming_webview_message(message);
Expand Down
54 changes: 52 additions & 2 deletions src/verso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl Verso {

// Initialize servo media with dummy backend
// This will create a thread to initialize a global static of servo media.
// The thread will be closed once the static is initialzed.
// The thread will be closed once the static is initialized.
// TODO: This is used by content process. Spawn it there once if we have multiprocess mode.
servo_media::ServoMedia::init::<servo_media_dummy::DummyBackend>();

Expand Down Expand Up @@ -412,8 +412,42 @@ impl Verso {
verso
}

/// Handle Winit window events. The strategy to handle event are different between platforms
/// because the order of events might be different.
pub fn handle_window_event(
&mut self,
event_loop: &ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
#[cfg(linux)]
if let WindowEvent::Resized(_) = event {
self.handle_winit_window_event(window_id, event);
} else {
self.handle_winit_window_event(window_id, event);
self.handle_servo_messages(event_loop);
}

#[cfg(apple)]
if let WindowEvent::RedrawRequested = event {
let resizing = self.handle_winit_window_event(window_id, event);
if !resizing {
self.handle_servo_messages(event_loop);
}
} else {
self.handle_winit_window_event(window_id, event);
self.handle_servo_messages(event_loop);
}

#[cfg(windows)]
{
self.handle_winit_window_event(window_id, event);
self.handle_servo_messages(event_loop);
}
}

/// Handle Winit window events
pub fn handle_winit_window_event(&mut self, window_id: WindowId, event: WindowEvent) {
fn handle_winit_window_event(&mut self, window_id: WindowId, event: WindowEvent) -> bool {
log::trace!("Verso is handling Winit event: {event:?}");
if let Some(compositor) = &mut self.compositor {
if let WindowEvent::CloseRequested = event {
Expand All @@ -423,8 +457,11 @@ impl Verso {
window
.0
.handle_winit_window_event(&self.constellation_sender, compositor, &event);
return window.0.resizing;
}
}

false
}

/// Handle message came from Servo.
Expand Down Expand Up @@ -518,6 +555,18 @@ impl Verso {
}
}

/// Request Verso to redraw. It will queue a redraw event on current focused window.
pub fn request_redraw(&mut self, evl: &ActiveEventLoop) {
if let Some(compositor) = &mut self.compositor {
if let Some(window) = self.windows.get(&compositor.current_window) {
// evl.set_control_flow(ControlFlow::Poll);
window.0.request_redraw();
} else {
self.handle_servo_messages(evl);
}
}
}

/// Handle message came from webview controller.
pub fn handle_incoming_webview_message(&self, message: ControllerMessage) {
match message {
Expand Down Expand Up @@ -558,6 +607,7 @@ impl Verso {
}

/// Message send to the event loop
#[derive(Debug)]
pub enum EventLoopProxyMessage {
/// Wake
Wake,
Expand Down
13 changes: 12 additions & 1 deletion src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ pub struct Window {
mouse_position: Cell<Option<PhysicalPosition<f64>>>,
/// Modifiers state of the keyboard.
modifiers_state: Cell<ModifiersState>,
/// State to indicate if the window is resizing.
pub(crate) resizing: bool,
}

impl Window {
Expand Down Expand Up @@ -94,6 +96,7 @@ impl Window {
webview: None,
mouse_position: Default::default(),
modifiers_state: Cell::new(ModifiersState::default()),
resizing: false,
},
rendering_context,
)
Expand Down Expand Up @@ -130,6 +133,7 @@ impl Window {
webview: None,
mouse_position: Default::default(),
modifiers_state: Cell::new(ModifiersState::default()),
resizing: false,
};
compositor.swap_current_window(&mut window);
window
Expand Down Expand Up @@ -200,6 +204,7 @@ impl Window {
match event {
WindowEvent::RedrawRequested => {
if compositor.ready_to_present {
self.window.pre_present_notify();
if let Err(err) = compositor.rendering_context.present(&self.surface) {
log::warn!("Failed to present surface: {:?}", err);
}
Expand All @@ -212,6 +217,9 @@ impl Window {
}
}
WindowEvent::Resized(size) => {
if self.window.has_focus() {
self.resizing = true;
}
let size = Size2D::new(size.width, size.height);
compositor.resize(size.to_i32(), self);
}
Expand Down Expand Up @@ -272,7 +280,10 @@ impl Window {

let event: MouseWindowEvent = match state {
ElementState::Pressed => MouseWindowEvent::MouseDown(button, position),
ElementState::Released => MouseWindowEvent::MouseUp(button, position),
ElementState::Released => {
self.resizing = false;
MouseWindowEvent::MouseUp(button, position)
}
};
compositor.on_mouse_window_event_class(event);

Expand Down