Add Event and EventTarget hierarchy via gross AbstractFoo mechanism.

This commit is contained in:
Josh Matthews 2013-10-01 17:01:46 -04:00
parent 7ecf5abbbd
commit bb97fd13f3
9 changed files with 327 additions and 86 deletions

View file

@ -182,6 +182,9 @@ DOMInterfaces = {
}, },
'Event': { 'Event': {
'nativeType': 'AbstractEvent',
'concreteType': 'Event',
'pointerType': '',
}, },
'EventListener': { 'EventListener': {
@ -189,6 +192,10 @@ DOMInterfaces = {
}, },
'EventTarget': { 'EventTarget': {
'nativeType': 'AbstractEventTarget',
'concreteType': 'EventTarget',
'pointerType': '',
'needsAbstract': ['dispatchEvent']
}, },
'FileList': [ 'FileList': [
@ -277,6 +284,9 @@ DOMInterfaces = {
}], }],
'MouseEvent': { 'MouseEvent': {
'nativeType': 'AbstractEvent',
'concreteType': 'MouseEvent',
'pointerType': '',
}, },
'Navigator': { 'Navigator': {
@ -374,6 +384,9 @@ DOMInterfaces = {
}], }],
'UIEvent': { 'UIEvent': {
'nativeType': 'AbstractEvent',
'concreteType': 'UIEvent',
'pointerType': '',
}, },
'ValidityState': { 'ValidityState': {

View file

@ -2410,12 +2410,13 @@ class Argument():
""" """
A class for outputting the type and name of an argument A class for outputting the type and name of an argument
""" """
def __init__(self, argType, name, default=None): def __init__(self, argType, name, default=None, mutable=False):
self.argType = argType self.argType = argType
self.name = name self.name = name
self.default = default self.default = default
self.mutable = mutable
def declare(self): def declare(self):
string = self.name + ((': ' + self.argType) if self.argType else '') string = ('mut ' if self.mutable else '') + self.name + ((': ' + self.argType) if self.argType else '')
#XXXjdm Support default arguments somehow :/ #XXXjdm Support default arguments somehow :/
#if self.default is not None: #if self.default is not None:
# string += " = " + self.default # string += " = " + self.default
@ -5225,6 +5226,8 @@ class CGBindingRoot(CGThing):
'dom::bindings::proxyhandler::*', 'dom::bindings::proxyhandler::*',
'dom::document::AbstractDocument', 'dom::document::AbstractDocument',
'dom::node::{AbstractNode, ScriptView}', 'dom::node::{AbstractNode, ScriptView}',
'dom::eventtarget::AbstractEventTarget',
'dom::event::AbstractEvent',
'servo_util::vec::zip_copies', 'servo_util::vec::zip_copies',
'std::cast', 'std::cast',
'std::libc', 'std::libc',
@ -5652,6 +5655,11 @@ class CGCallback(CGClass):
# CallSetup should re-throw exceptions on aRv. # CallSetup should re-throw exceptions on aRv.
args.append(Argument("ExceptionHandling", "aExceptionHandling", args.append(Argument("ExceptionHandling", "aExceptionHandling",
"eReportExceptions")) "eReportExceptions"))
# Ensure the first argument is mutable
args[0] = Argument(args[0].argType, args[0].name, args[0].default, mutable=True)
method.args[2] = args[0]
# And now insert our template argument. # And now insert our template argument.
argsWithoutThis = list(args) argsWithoutThis = list(args)
args.insert(0, Argument("@mut T", "thisObj")) args.insert(0, Argument("@mut T", "thisObj"))
@ -5661,7 +5669,7 @@ class CGCallback(CGClass):
args.insert(0, Argument(None, "&self")) args.insert(0, Argument(None, "&self"))
argsWithoutThis.insert(0, Argument(None, "&self")) argsWithoutThis.insert(0, Argument(None, "&self"))
setupCall = ("let s = CallSetup::new(cx_for_dom_object(${cxProvider}), aExceptionHandling);\n" setupCall = ("let s = CallSetup::new(cx_for_dom_object(&mut ${cxProvider}), aExceptionHandling);\n"
"if s.GetContext().is_null() {\n" "if s.GetContext().is_null() {\n"
" return${errorReturn};\n" " return${errorReturn};\n"
"}\n") "}\n")
@ -5676,7 +5684,7 @@ class CGCallback(CGClass):
"errorReturn" : method.getDefaultRetval(), "errorReturn" : method.getDefaultRetval(),
"callArgs" : ", ".join(argnamesWithThis), "callArgs" : ", ".join(argnamesWithThis),
"methodName": 'self.' + method.name, "methodName": 'self.' + method.name,
"cxProvider": 'thisObj' "cxProvider": '*thisObj'
}) })
bodyWithoutThis = string.Template( bodyWithoutThis = string.Template(
setupCall + setupCall +

View file

@ -768,6 +768,7 @@ pub enum Error {
NotFound, NotFound,
HierarchyRequest, HierarchyRequest,
InvalidCharacter, InvalidCharacter,
NotSupported
} }
pub type Fallible<T> = Result<T, Error>; pub type Fallible<T> = Result<T, Error>;
@ -841,7 +842,7 @@ pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject {
} }
#[fixed_stack_segment] #[fixed_stack_segment]
fn cx_for_dom_wrapper(obj: *JSObject) -> *JSContext { fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext {
unsafe { unsafe {
let global = GetGlobalForObjectCrossCompartment(obj); let global = GetGlobalForObjectCrossCompartment(obj);
let clasp = JS_GetClass(global); let clasp = JS_GetClass(global);
@ -860,8 +861,8 @@ fn cx_for_dom_wrapper(obj: *JSObject) -> *JSContext {
} }
} }
pub fn cx_for_dom_object<T: Reflectable>(obj: @mut T) -> *JSContext { pub fn cx_for_dom_object<T: Reflectable>(obj: &mut T) -> *JSContext {
cx_for_dom_wrapper(obj.reflector().get_jsobject()) cx_for_dom_reflector(obj.reflector().get_jsobject())
} }
/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name /// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name

View file

@ -5,16 +5,20 @@
use dom::comment::Comment; use dom::comment::Comment;
use dom::bindings::codegen::DocumentBinding; use dom::bindings::codegen::DocumentBinding;
use dom::bindings::utils::{DOMString, ErrorResult, Fallible}; use dom::bindings::utils::{DOMString, ErrorResult, Fallible};
use dom::bindings::utils::{Reflectable, Reflector, DerivedWrapper}; use dom::bindings::utils::{Reflectable, Reflector, DerivedWrapper, NotSupported};
use dom::bindings::utils::{is_valid_element_name, InvalidCharacter, Traceable, null_str_as_empty, null_str_as_word_null}; use dom::bindings::utils::{is_valid_element_name, InvalidCharacter, Traceable};
use dom::bindings::utils::{null_str_as_empty_ref, null_str_as_empty, null_str_as_word_null};
use dom::documentfragment::DocumentFragment; use dom::documentfragment::DocumentFragment;
use dom::element::{Element}; use dom::element::{Element};
use dom::element::{HTMLHeadElementTypeId, HTMLTitleElementTypeId}; use dom::element::{HTMLHeadElementTypeId, HTMLTitleElementTypeId};
use dom::event::Event; use dom::event::{AbstractEvent, Event, HTMLEventTypeId, UIEventTypeId};
use dom::htmlcollection::HTMLCollection; use dom::htmlcollection::HTMLCollection;
use dom::htmldocument::HTMLDocument; use dom::htmldocument::HTMLDocument;
use dom::htmlelement::HTMLElement;
use dom::mouseevent::MouseEvent;
use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId, DocumentNodeTypeId}; use dom::node::{AbstractNode, ScriptView, Node, ElementNodeTypeId, DocumentNodeTypeId};
use dom::text::Text; use dom::text::Text;
use dom::uievent::UIEvent;
use dom::window::Window; use dom::window::Window;
use dom::htmltitleelement::HTMLTitleElement; use dom::htmltitleelement::HTMLTitleElement;
use html::hubbub_html_parser::build_element_from_tag; use html::hubbub_html_parser::build_element_from_tag;
@ -256,9 +260,13 @@ impl Document {
Comment::new(null_str_as_word_null(data), abstract_self) Comment::new(null_str_as_word_null(data), abstract_self)
} }
pub fn CreateEvent(&self, interface: &DOMString) -> Fallible<@mut Event> { pub fn CreateEvent(&self, interface: &DOMString) -> Fallible<AbstractEvent> {
//FIXME: We need to do a proper Event inheritance simulation match null_str_as_empty_ref(interface) {
Ok(Event::new(self.window, interface)) "UIEvents" => Ok(UIEvent::new(self.window, UIEventTypeId)),
"MouseEvents" => Ok(MouseEvent::new(self.window)),
"HTMLEvents" => Ok(Event::new(self.window, HTMLEventTypeId)),
_ => Err(NotSupported)
}
} }
pub fn Title(&self, _: AbstractDocument) -> DOMString { pub fn Title(&self, _: AbstractDocument) -> DOMString {

View file

@ -2,17 +2,23 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::eventtarget::EventTarget; use dom::eventtarget::AbstractEventTarget;
use dom::window::Window; use dom::window::Window;
use dom::bindings::codegen::EventBinding; use dom::bindings::codegen::EventBinding;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object, DerivedWrapper};
use dom::bindings::utils::{DOMString, ErrorResult, Fallible, null_str_as_word_null}; use dom::bindings::utils::{DOMString, ErrorResult, Fallible, null_str_as_word_null};
use dom::mouseevent::MouseEvent;
use dom::uievent::UIEvent;
use geom::point::Point2D; use geom::point::Point2D;
use js::jsapi::{JSObject, JSContext}; use js::jsapi::{JSObject, JSContext, JSVal};
use js::glue::RUST_OBJECT_TO_JSVAL;
use script_task::page_from_context; use script_task::page_from_context;
use std::cast;
use std::unstable::raw::Box;
pub enum Event_ { pub enum Event_ {
ResizeEvent(uint, uint), ResizeEvent(uint, uint),
ReflowEvent, ReflowEvent,
@ -21,7 +27,116 @@ pub enum Event_ {
MouseUpEvent(uint, Point2D<f32>), MouseUpEvent(uint, Point2D<f32>),
} }
pub struct AbstractEvent {
event: *mut Box<Event>
}
impl AbstractEvent {
pub fn from_box(box: *mut Box<Event>) -> AbstractEvent {
AbstractEvent {
event: box
}
}
//
// Downcasting borrows
//
fn transmute<'a, T>(&'a self) -> &'a T {
unsafe {
let box: *Box<T> = self.event as *Box<T>;
&(*box).data
}
}
fn transmute_mut<'a, T>(&'a self) -> &'a mut T {
unsafe {
let box: *mut Box<T> = self.event as *mut Box<T>;
&mut (*box).data
}
}
pub fn type_id(&self) -> EventTypeId {
self.event().type_id
}
pub fn event<'a>(&'a self) -> &'a Event {
self.transmute()
}
pub fn mut_event<'a>(&'a self) -> &'a mut Event {
self.transmute_mut()
}
pub fn is_uievent(&self) -> bool {
self.type_id() == UIEventTypeId
}
pub fn uievent<'a>(&'a self) -> &'a UIEvent {
assert!(self.is_uievent());
self.transmute()
}
pub fn mut_uievent<'a>(&'a self) -> &'a mut UIEvent {
assert!(self.is_uievent());
self.transmute_mut()
}
pub fn is_mouseevent(&self) -> bool {
self.type_id() == MouseEventTypeId
}
pub fn mouseevent<'a>(&'a self) -> &'a MouseEvent {
assert!(self.is_mouseevent());
self.transmute()
}
pub fn mut_mouseevent<'a>(&'a self) -> &'a mut MouseEvent {
assert!(self.is_mouseevent());
self.transmute_mut()
}
}
impl DerivedWrapper for AbstractEvent {
#[fixed_stack_segment]
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, vp: *mut JSVal) -> i32 {
let wrapper = self.reflector().get_jsobject();
if wrapper.is_not_null() {
unsafe { *vp = RUST_OBJECT_TO_JSVAL(wrapper) };
return 1;
}
unreachable!()
}
}
impl Reflectable for AbstractEvent {
fn reflector<'a>(&'a self) -> &'a Reflector {
self.event().reflector()
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
self.mut_event().mut_reflector()
}
fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"doesn't make any sense");
}
fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> {
self.event().GetParentObject(cx)
}
}
#[deriving(Eq)]
pub enum EventTypeId {
HTMLEventTypeId,
UIEventTypeId,
MouseEventTypeId,
KeyEventTypeId
}
pub struct Event { pub struct Event {
type_id: EventTypeId,
reflector_: Reflector, reflector_: Reflector,
type_: ~str, type_: ~str,
default_prevented: bool, default_prevented: bool,
@ -31,10 +146,11 @@ pub struct Event {
} }
impl Event { impl Event {
pub fn new_inherited(type_: &DOMString) -> Event { pub fn new_inherited(type_id: EventTypeId) -> Event {
Event { Event {
type_id: type_id,
reflector_: Reflector::new(), reflector_: Reflector::new(),
type_: null_str_as_word_null(type_), type_: ~"",
default_prevented: false, default_prevented: false,
cancelable: true, cancelable: true,
bubbles: true, bubbles: true,
@ -42,8 +158,18 @@ impl Event {
} }
} }
pub fn new(window: @mut Window, type_: &DOMString) -> @mut Event { //FIXME: E should be bounded by some trait that is only implemented for Event types
reflect_dom_object(@mut Event::new_inherited(type_), window, EventBinding::Wrap) pub fn as_abstract<E>(event: @mut E) -> AbstractEvent {
// This surrenders memory management of the event!
AbstractEvent {
event: unsafe { cast::transmute(event) },
}
}
pub fn new(window: @mut Window, type_id: EventTypeId) -> AbstractEvent {
let ev = reflect_dom_object(@mut Event::new_inherited(type_id), window,
EventBinding::Wrap);
Event::as_abstract(ev)
} }
pub fn EventPhase(&self) -> u16 { pub fn EventPhase(&self) -> u16 {
@ -54,11 +180,11 @@ impl Event {
Some(self.type_.clone()) Some(self.type_.clone())
} }
pub fn GetTarget(&self) -> Option<@mut EventTarget> { pub fn GetTarget(&self) -> Option<AbstractEventTarget> {
None None
} }
pub fn GetCurrentTarget(&self) -> Option<@mut EventTarget> { pub fn GetCurrentTarget(&self) -> Option<AbstractEventTarget> {
None None
} }
@ -92,7 +218,7 @@ impl Event {
type_: &DOMString, type_: &DOMString,
bubbles: bool, bubbles: bool,
cancelable: bool) -> ErrorResult { cancelable: bool) -> ErrorResult {
self.type_ = type_.to_str(); self.type_ = null_str_as_word_null(type_);
self.cancelable = cancelable; self.cancelable = cancelable;
self.bubbles = bubbles; self.bubbles = bubbles;
Ok(()) Ok(())
@ -104,8 +230,10 @@ impl Event {
pub fn Constructor(global: @mut Window, pub fn Constructor(global: @mut Window,
type_: &DOMString, type_: &DOMString,
_init: &EventBinding::EventInit) -> Fallible<@mut Event> { init: &EventBinding::EventInit) -> Fallible<AbstractEvent> {
Ok(Event::new(global, type_)) let ev = Event::new(global, HTMLEventTypeId);
ev.mut_event().InitEvent(type_, init.bubbles, init.cancelable);
Ok(ev)
} }
} }

View file

@ -4,14 +4,19 @@
use dom::bindings::callback::eReportExceptions; use dom::bindings::callback::eReportExceptions;
use dom::bindings::codegen::EventTargetBinding; use dom::bindings::codegen::EventTargetBinding;
use dom::bindings::utils::{Reflectable, Reflector, DOMString, Fallible}; use dom::bindings::utils::{Reflectable, Reflector, DOMString, Fallible, DerivedWrapper};
use dom::bindings::utils::null_str_as_word_null;
use dom::bindings::codegen::EventListenerBinding::EventListener; use dom::bindings::codegen::EventListenerBinding::EventListener;
use dom::event::Event; use dom::event::AbstractEvent;
use dom::node::{AbstractNode, ScriptView};
use script_task::page_from_context; use script_task::page_from_context;
use js::jsapi::{JSObject, JSContext}; use js::jsapi::{JSObject, JSContext, JSVal};
use js::glue::RUST_OBJECT_TO_JSVAL;
use std::cast;
use std::hashmap::HashMap; use std::hashmap::HashMap;
use std::unstable::raw::Box;
pub struct EventTarget { pub struct EventTarget {
reflector_: Reflector, reflector_: Reflector,
@ -19,6 +24,80 @@ pub struct EventTarget {
bubbling_handlers: HashMap<~str, ~[EventListener]> bubbling_handlers: HashMap<~str, ~[EventListener]>
} }
pub struct AbstractEventTarget {
eventtarget: *mut Box<EventTarget>
}
impl AbstractEventTarget {
pub fn from_box(box: *mut Box<EventTarget>) -> AbstractEventTarget {
AbstractEventTarget {
eventtarget: box
}
}
pub fn from_node(node: AbstractNode<ScriptView>) -> AbstractEventTarget {
unsafe {
cast::transmute(node)
}
}
//
// Downcasting borrows
//
fn transmute<'a, T>(&'a self) -> &'a T {
unsafe {
let box: *Box<T> = self.eventtarget as *Box<T>;
&(*box).data
}
}
fn transmute_mut<'a, T>(&'a mut self) -> &'a mut T {
unsafe {
let box: *mut Box<T> = self.eventtarget as *mut Box<T>;
&mut (*box).data
}
}
fn eventtarget<'a>(&'a self) -> &'a EventTarget {
self.transmute()
}
fn mut_eventtarget<'a>(&'a mut self) -> &'a mut EventTarget {
self.transmute_mut()
}
}
impl DerivedWrapper for AbstractEventTarget {
#[fixed_stack_segment]
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, vp: *mut JSVal) -> i32 {
let wrapper = self.reflector().get_jsobject();
if wrapper.is_not_null() {
unsafe { *vp = RUST_OBJECT_TO_JSVAL(wrapper) };
return 1;
}
unreachable!()
}
}
impl Reflectable for AbstractEventTarget {
fn reflector<'a>(&'a self) -> &'a Reflector {
self.eventtarget().reflector()
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
self.mut_eventtarget().mut_reflector()
}
fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
unreachable!()
}
fn GetParentObject(&self, cx: *JSContext) -> Option<@mut Reflectable> {
self.eventtarget().GetParentObject(cx)
}
}
impl EventTarget { impl EventTarget {
pub fn new() -> EventTarget { pub fn new() -> EventTarget {
EventTarget { EventTarget {
@ -46,7 +125,7 @@ impl EventTarget {
} else { } else {
&mut self.bubbling_handlers &mut self.bubbling_handlers
}; };
let entry = handlers.find_or_insert_with(ty.to_str(), |_| ~[]); let entry = handlers.find_or_insert_with(null_str_as_word_null(ty), |_| ~[]);
if entry.position_elem(listener).is_none() { if entry.position_elem(listener).is_none() {
entry.push((*listener).clone()); entry.push((*listener).clone());
} }
@ -63,7 +142,7 @@ impl EventTarget {
} else { } else {
&mut self.bubbling_handlers &mut self.bubbling_handlers
}; };
let mut entry = handlers.find_mut(&ty.to_str()); let mut entry = handlers.find_mut(&null_str_as_word_null(ty));
for entry in entry.mut_iter() { for entry in entry.mut_iter() {
let position = entry.position_elem(listener); let position = entry.position_elem(listener);
for &position in position.iter() { for &position in position.iter() {
@ -73,24 +152,25 @@ impl EventTarget {
} }
} }
pub fn DispatchEvent(&self, event: @mut Event) -> Fallible<bool> { pub fn DispatchEvent(&self, _abstract_self: AbstractEventTarget, event: AbstractEvent) -> Fallible<bool> {
//FIXME: get proper |this| object //FIXME: get proper |this| object
let maybe_handlers = self.capturing_handlers.find(&event.type_); let type_ = event.event().type_.clone();
let maybe_handlers = self.capturing_handlers.find(&type_);
for handlers in maybe_handlers.iter() { for handlers in maybe_handlers.iter() {
for handler in handlers.iter() { for handler in handlers.iter() {
handler.HandleEvent__(event, eReportExceptions); handler.HandleEvent__(event, eReportExceptions);
} }
} }
if event.bubbles { if event.event().bubbles {
let maybe_handlers = self.bubbling_handlers.find(&event.type_); let maybe_handlers = self.bubbling_handlers.find(&type_);
for handlers in maybe_handlers.iter() { for handlers in maybe_handlers.iter() {
for handler in handlers.iter() { for handler in handlers.iter() {
handler.HandleEvent__(event, eReportExceptions); handler.HandleEvent__(event, eReportExceptions);
} }
} }
} }
Ok(!event.DefaultPrevented()) Ok(!event.event().DefaultPrevented())
} }
} }

View file

@ -5,7 +5,8 @@
use dom::bindings::codegen::MouseEventBinding; use dom::bindings::codegen::MouseEventBinding;
use dom::bindings::utils::{ErrorResult, Fallible, DOMString}; use dom::bindings::utils::{ErrorResult, Fallible, DOMString};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::EventTarget; use dom::event::{AbstractEvent, Event, MouseEventTypeId};
use dom::eventtarget::AbstractEventTarget;
use dom::uievent::UIEvent; use dom::uievent::UIEvent;
use dom::window::Window; use dom::window::Window;
use dom::windowproxy::WindowProxy; use dom::windowproxy::WindowProxy;
@ -23,38 +24,42 @@ pub struct MouseEvent {
alt_key: bool, alt_key: bool,
meta_key: bool, meta_key: bool,
button: u16, button: u16,
related_target: Option<@mut EventTarget> related_target: Option<AbstractEventTarget>
} }
impl MouseEvent { impl MouseEvent {
pub fn new(window: @mut Window, type_: &DOMString, can_bubble: bool, cancelable: bool, pub fn new_inherited() -> MouseEvent {
view: Option<@mut WindowProxy>, detail: i32, screen_x: i32, MouseEvent {
screen_y: i32, client_x: i32, client_y: i32, ctrl_key: bool, parent: UIEvent::new_inherited(MouseEventTypeId),
shift_key: bool, alt_key: bool, meta_key: bool, button: u16, screen_x: 0,
_buttons: u16, related_target: Option<@mut EventTarget>) -> @mut MouseEvent { screen_y: 0,
let ev = @mut MouseEvent { client_x: 0,
parent: UIEvent::new_inherited(type_, can_bubble, cancelable, view, detail), client_y: 0,
screen_x: screen_x, ctrl_key: false,
screen_y: screen_y, shift_key: false,
client_x: client_x, alt_key: false,
client_y: client_y, meta_key: false,
ctrl_key: ctrl_key, button: 0,
shift_key: shift_key, related_target: None
alt_key: alt_key, }
meta_key: meta_key, }
button: button,
related_target: related_target pub fn new(window: @mut Window) -> AbstractEvent {
}; Event::as_abstract(reflect_dom_object(@mut MouseEvent::new_inherited(),
reflect_dom_object(ev, window, MouseEventBinding::Wrap) window,
MouseEventBinding::Wrap))
} }
pub fn Constructor(owner: @mut Window, pub fn Constructor(owner: @mut Window,
type_: &DOMString, type_: &DOMString,
init: &MouseEventBinding::MouseEventInit) -> Fallible<@mut MouseEvent> { init: &MouseEventBinding::MouseEventInit) -> Fallible<AbstractEvent> {
Ok(MouseEvent::new(owner, type_, init.bubbles, init.cancelable, init.view, init.detail, let ev = MouseEvent::new(owner);
init.screenX, init.screenY, init.clientX, init.clientY, ev.mut_mouseevent().InitMouseEvent(type_, init.bubbles, init.cancelable, init.view,
init.ctrlKey, init.shiftKey, init.altKey, init.metaKey, init.detail, init.screenX, init.screenY,
init.button, init.buttons, init.relatedTarget)) init.clientX, init.clientY, init.ctrlKey,
init.altKey, init.shiftKey, init.metaKey,
init.button, init.relatedTarget);
Ok(ev)
} }
pub fn ScreenX(&self) -> i32 { pub fn ScreenX(&self) -> i32 {
@ -98,7 +103,7 @@ impl MouseEvent {
0 0
} }
pub fn GetRelatedTarget(&self) -> Option<@mut EventTarget> { pub fn GetRelatedTarget(&self) -> Option<AbstractEventTarget> {
self.related_target self.related_target
} }
@ -122,7 +127,7 @@ impl MouseEvent {
shiftKeyArg: bool, shiftKeyArg: bool,
metaKeyArg: bool, metaKeyArg: bool,
buttonArg: u16, buttonArg: u16,
relatedTargetArg: Option<@mut EventTarget>) -> ErrorResult { relatedTargetArg: Option<AbstractEventTarget>) -> ErrorResult {
self.parent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); self.parent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
self.screen_x = screenXArg; self.screen_x = screenXArg;
self.screen_y = screenYArg; self.screen_y = screenYArg;

View file

@ -6,7 +6,7 @@ use dom::bindings::codegen::UIEventBinding;
use dom::bindings::utils::{DOMString, Fallible}; use dom::bindings::utils::{DOMString, Fallible};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::node::{AbstractNode, ScriptView}; use dom::node::{AbstractNode, ScriptView};
use dom::event::Event; use dom::event::{AbstractEvent, Event, EventTypeId, UIEventTypeId};
use dom::window::Window; use dom::window::Window;
use dom::windowproxy::WindowProxy; use dom::windowproxy::WindowProxy;
@ -14,36 +14,33 @@ use js::jsapi::{JSObject, JSContext};
pub struct UIEvent { pub struct UIEvent {
parent: Event, parent: Event,
can_bubble: bool,
cancelable: bool,
view: Option<@mut WindowProxy>, view: Option<@mut WindowProxy>,
detail: i32 detail: i32
} }
impl UIEvent { impl UIEvent {
pub fn new_inherited(type_: &DOMString, can_bubble: bool, cancelable: bool, pub fn new_inherited(type_id: EventTypeId) -> UIEvent {
view: Option<@mut WindowProxy>, detail: i32) -> UIEvent {
UIEvent { UIEvent {
parent: Event::new_inherited(type_), parent: Event::new_inherited(type_id),
can_bubble: can_bubble, view: None,
cancelable: cancelable, detail: 0
view: view,
detail: detail
} }
} }
pub fn new(window: @mut Window, type_: &DOMString, can_bubble: bool, cancelable: bool, pub fn new(window: @mut Window, type_id: EventTypeId) -> AbstractEvent {
view: Option<@mut WindowProxy>, detail: i32) -> @mut UIEvent { let ev = reflect_dom_object(@mut UIEvent::new_inherited(type_id),
reflect_dom_object(@mut UIEvent::new_inherited(type_, can_bubble, cancelable, view, detail),
window, window,
UIEventBinding::Wrap) UIEventBinding::Wrap);
Event::as_abstract(ev)
} }
pub fn Constructor(owner: @mut Window, pub fn Constructor(owner: @mut Window,
type_: &DOMString, type_: &DOMString,
init: &UIEventBinding::UIEventInit) -> Fallible<@mut UIEvent> { init: &UIEventBinding::UIEventInit) -> Fallible<AbstractEvent> {
Ok(UIEvent::new(owner, type_, init.parent.bubbles, init.parent.cancelable, let ev = UIEvent::new(owner, UIEventTypeId);
init.view, init.detail)) ev.mut_uievent().InitUIEvent(type_, init.parent.bubbles, init.parent.cancelable,
init.view, init.detail);
Ok(ev)
} }
pub fn GetView(&self) -> Option<@mut WindowProxy> { pub fn GetView(&self) -> Option<@mut WindowProxy> {
@ -61,8 +58,6 @@ impl UIEvent {
view: Option<@mut WindowProxy>, view: Option<@mut WindowProxy>,
detail: i32) { detail: i32) {
self.parent.InitEvent(type_, can_bubble, cancelable); self.parent.InitEvent(type_, can_bubble, cancelable);
self.can_bubble = can_bubble;
self.cancelable = cancelable;
self.view = view; self.view = view;
self.detail = detail; self.detail = detail;
} }

View file

@ -4,14 +4,17 @@
</head> </head>
<body> <body>
<script> <script>
var saw_event = false;
function onFoopy() { function onFoopy() {
window.removeEventListener('foopy', onFoopy); window.removeEventListener('foopy', onFoopy);
finish(); saw_event = true;
} }
window.addEventListener('foopy', onFoopy); window.addEventListener('foopy', onFoopy);
var ev = document.createEvent('Event'); var ev = document.createEvent('HTMLEvents');
ev.initEvent('foopy', true, true); ev.initEvent('foopy', true, true);
window.dispatchEvent(ev); window.dispatchEvent(ev);
is(saw_event, true);
finish();
</script> </script>
</body> </body>
</html> </html>