diff options
Diffstat (limited to 'src/components/script/dom/window.rs')
-rw-r--r-- | src/components/script/dom/window.rs | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs new file mode 100644 index 00000000000..c94e6488a67 --- /dev/null +++ b/src/components/script/dom/window.rs @@ -0,0 +1,119 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::utils::WrapperCache; +use dom::bindings::window; +use layout_interface::MatchSelectorsDamage; +use script_task::{ExitMsg, FireTimerMsg, ScriptMsg, ScriptContext}; + +use core::comm::{Chan, SharedChan}; +use js::jsapi::JSVal; +use std::timer; +use std::uv_global_loop; + +pub enum TimerControlMsg { + TimerMessage_Fire(~TimerData), + TimerMessage_Close, + TimerMessage_TriggerExit //XXXjdm this is just a quick hack to talk to the script task +} + +//FIXME If we're going to store the script task, find a way to do so safely. Currently it's +// only used for querying layout from arbitrary script. +pub struct Window { + timer_chan: Chan<TimerControlMsg>, + script_chan: SharedChan<ScriptMsg>, + script_context: *mut ScriptContext, + wrapper: WrapperCache +} + +impl Drop for Window { + fn finalize(&self) { + self.timer_chan.send(TimerMessage_Close); + } +} + +// Holder for the various JS values associated with setTimeout +// (ie. function value to invoke and all arguments to pass +// to the function when calling it) +pub struct TimerData { + funval: JSVal, + args: ~[JSVal], +} + +pub fn TimerData(argc: libc::c_uint, argv: *JSVal) -> TimerData { + unsafe { + let mut args = ~[]; + + let mut i = 2; + while i < argc as uint { + args.push(*ptr::offset(argv, i)); + i += 1; + }; + + TimerData { + funval : *argv, + args : args, + } + } +} + +// FIXME: delayed_send shouldn't require Copy +#[allow(non_implicitly_copyable_typarams)] +pub impl Window { + fn alert(&self, s: &str) { + // Right now, just print to the console + io::println(fmt!("ALERT: %s", s)); + } + + fn close(&self) { + self.timer_chan.send(TimerMessage_TriggerExit); + } + + fn setTimeout(&self, timeout: int, argc: libc::c_uint, argv: *JSVal) { + let timeout = int::max(0, timeout) as uint; + + // Post a delayed message to the per-window timer task; it will dispatch it + // to the relevant script handler that will deal with it. + timer::delayed_send(&uv_global_loop::get(), + timeout, + &self.timer_chan, + TimerMessage_Fire(~TimerData(argc, argv))); + } + + fn content_changed(&self) { + unsafe { + (*self.script_context).trigger_relayout(MatchSelectorsDamage); + } + } + + pub fn new(script_chan: SharedChan<ScriptMsg>, script_context: *mut ScriptContext) + -> @mut Window { + let script_chan_copy = script_chan.clone(); + let win = @mut Window { + wrapper: WrapperCache::new(), + script_chan: script_chan, + timer_chan: { + let (timer_port, timer_chan) = comm::stream::<TimerControlMsg>(); + do spawn { + loop { + match timer_port.recv() { + TimerMessage_Close => break, + TimerMessage_Fire(td) => script_chan_copy.send(FireTimerMsg(td)), + TimerMessage_TriggerExit => script_chan_copy.send(ExitMsg), + } + } + } + timer_chan + }, + script_context: script_context, + }; + + unsafe { + let compartment = (*script_context).js_compartment; + window::create(compartment, win); + } + win + } +} + |