Rate limit resize events

This commit is contained in:
Brian Anderson 2012-10-14 04:07:34 -07:00
parent a06d45f2a5
commit c41ff73847
5 changed files with 78 additions and 5 deletions

View file

@ -326,7 +326,7 @@ impl Content {
// TODO: actually perform DOM event dispatch.
fn handle_event(event: Event) -> bool {
match event {
ResizeEvent(new_width, new_height) => {
ResizeEvent(new_width, new_height, response_chan) => {
debug!("content got resize event: %u, %u", new_width, new_height);
self.window_size = Size2D(new_width, new_height);
match copy self.document {
@ -338,6 +338,7 @@ impl Content {
self.relayout(document, &self.doc_url.get());
}
}
response_chan.send(());
return true;
}
ReflowEvent => {

View file

@ -1,5 +1,5 @@
enum Event {
ResizeEvent(uint, uint),
ResizeEvent(uint, uint, pipes::Chan<()>),
ReflowEvent
}

View file

@ -15,6 +15,7 @@ use task::TaskBuilder;
use vec::push;
use pipes::Chan;
use std::cell::Cell;
use resize_rate_limiter::ResizeRateLimiter;
pub type OSMain = comm::Chan<Msg>;
@ -56,8 +57,6 @@ fn OSMain(dom_event_chan: pipes::SharedChan<Event>) -> OSMain {
fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<Event>) {
let dom_event_chan = @move dom_event_chan;
let key_handlers: @DVec<pipes::Chan<()>> = @DVec();
let window;
@ -90,12 +89,18 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E
let done = @mut false;
let resize_rate_limiter = @ResizeRateLimiter(move dom_event_chan);
#macro[
[#moov[x],
unsafe { let y <- *ptr::addr_of(x); y }]
];
let check_for_messages = fn@() {
// Periodically check if content responded to our last resize event
resize_rate_limiter.check_resize_response();
// Handle messages
#debug("osmain: peeking");
while po.peek() {
@ -136,7 +141,7 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E
check_for_messages();
#debug("osmain: window resized to %d,%d", width as int, height as int);
dom_event_chan.send(ResizeEvent(width as uint, height as uint));
resize_rate_limiter.window_resized(width as uint, height as uint);
}
do glut::display_func() {

View file

@ -0,0 +1,66 @@
/*!
A little class that rate limits the number of resize events sent to the content task
based on how fast content dispatches those events. It waits until each event is handled
before sending the next. If the window is resized multiple times before an event is handled
then some events will never be sent.
*/
use dom::event::{Event, ResizeEvent};
pub struct ResizeRateLimiter {
/// The channel we send resize events on
/* priv */ dom_event_chan: pipes::SharedChan<Event>,
/// The port we are waiting on for a response to the last resize event
/* priv */ mut last_response_port: Option<pipes::Port<()>>,
/// The next window resize event we should fire
/* priv */ mut next_resize_event: Option<(uint, uint)>
}
pub fn ResizeRateLimiter(dom_event_chan: pipes::SharedChan<Event>) -> ResizeRateLimiter {
ResizeRateLimiter {
dom_event_chan: move dom_event_chan,
last_response_port: None,
next_resize_event: None
}
}
impl ResizeRateLimiter {
fn window_resized(width: uint, height: uint) {
match self.last_response_port {
None => {
assert self.next_resize_event.is_none();
self.send_event(width, height);
}
Some(*) => {
if self.last_response_port.get_ref().peek() {
self.send_event(width, height);
self.next_resize_event = None;
} else {
if self.next_resize_event.is_some() {
warn!("osmain: content can't keep up. skipping resize event");
}
self.next_resize_event = Some((width, height));
}
}
}
}
fn check_resize_response() {
match self.next_resize_event {
Some((copy width, copy height)) => {
assert self.last_response_port.is_some();
if self.last_response_port.get_ref().peek() {
self.send_event(width, height);
self.next_resize_event = None;
}
}
None => ()
}
}
priv fn send_event(width: uint, height: uint) {
let (chan, port) = pipes::stream();
self.dom_event_chan.send(ResizeEvent(width, height, move chan));
self.last_response_port = Some(move port);
}
}

View file

@ -95,6 +95,7 @@ pub mod html {
pub mod platform {
pub mod base;
pub mod osmain;
priv mod resize_rate_limiter;
}
pub mod text {