Generate DOM bindings for UIEvent and MouseEvent.

This commit is contained in:
Josh Matthews 2013-07-10 16:41:08 -04:00
parent 8787c1ac1f
commit 65f9aefb78
12 changed files with 601 additions and 22 deletions

View file

@ -256,6 +256,9 @@ DOMInterfaces = {
'workers': True,
}],
'MouseEvent': {
},
'NodeList': [
{
'nativeType': 'nsINodeList',
@ -333,6 +336,9 @@ DOMInterfaces = {
'resultNotAddRefed': [ 'getItem' ]
}],
'UIEvent': {
},
'WebGLRenderingContext': {
'nativeType': 'mozilla::WebGLContext',
'headerFile': 'WebGLContext.h',
@ -499,7 +505,7 @@ def addExternalIface(iface, nativeType=None, headerFile=None, pointerType=None):
# If you add one of these, you need to make sure nsDOMQS.h has the relevant
# macros added for it
def addExternalHTMLElement(element):
nativeElement = 'ns' + element
nativeElement = element
addExternalIface(element, nativeType=nativeElement,
headerFile=nativeElement + '.h')
@ -520,7 +526,7 @@ addExternalIface('File')
addExternalIface('HitRegionOptions', nativeType='nsISupports')
addExternalIface('HTMLElement')
addExternalIface('ImageData', nativeType='mozilla::dom::ImageData')
addExternalIface('Node', nativeType='nsINode')
addExternalIface('Node', nativeType='AbstractNode<ScriptView>', pointerType='')
addExternalIface('PaintRequest')
addExternalIface('SVGLength')
addExternalIface('SVGMatrix')
@ -552,4 +558,5 @@ addExternalIface('WebGLShaderPrecisionFormat',
addExternalIface('WebGLTexture', nativeType='mozilla::WebGLTexture',
headerFile='WebGLContext.h')
addExternalIface('Window')
addExternalIface('WindowProxy', nativeType='WindowProxy')
addExternalIface('XULElement')

View file

@ -558,7 +558,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
CGIndenter(CGGeneric(templateBody)).define() + "\n")
if type.nullable():
templateBody += (
"} else if (${val}.isNullOrUndefined()) {\n"
"} else if RUST_JSVAL_IS_NULL(${val}) != 0 || RUST_JSVAL_IS_VOID(${val}) != 0 {\n"
" %s;\n" % codeToSetNull)
templateBody += (
"} else {\n" +
@ -893,7 +893,7 @@ for (uint32_t i = 0; i < length; ++i) {
not descriptor.workers) or isMember
typeName = descriptor.nativeType
typePtr = typeName + "*"
typePtr = descriptor.pointerType + typeName
# Compute a few things:
# - declType is the type we want to return as the first element of our
@ -904,15 +904,9 @@ for (uint32_t i = 0; i < length; ++i) {
# Set up some sensible defaults for these things insofar as we can.
holderType = None
if argIsPointer:
if forceOwningType:
declType = "nsRefPtr<" + typeName + ">"
declType = "Option<" + typePtr + ">"
else:
declType = typePtr
else:
if forceOwningType:
declType = "OwningNonNull<" + typeName + ">"
else:
declType = descriptor.pointerType + typeName
templateBody = ""
if descriptor.castable:
@ -1298,10 +1292,15 @@ def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
(holderType.define(), originalHolderName))
mutableHolderType = CGWrapper(holderType, pre="Optional< ", post=" >")
holderType = CGWrapper(mutableHolderType, pre="const ")
result.append(
CGList([holderType, CGGeneric(" "),
tmpresult = [CGGeneric("let "),
CGGeneric(originalHolderName),
CGGeneric(";")]))
CGGeneric(": "),
holderType]
if initialValue:
tmpresult += [CGGeneric(" = "),
initialValue]
tmpresult += [CGGeneric(";")]
result.append(CGList(tmpresult))
originalDeclName = replacements["declName"]
if declType is not None:
@ -4034,11 +4033,11 @@ class CGDictionary(CGThing):
def defaultValue(ty):
if ty is "bool":
return "false"
elif ty in ["i32", "u32"]:
elif ty in ["i32", "u32", "i16", "u16"]:
return "0"
elif ty is "nsString":
return "\"\""
elif ty.startswith("Optional"):
elif ty.startswith("Option"):
return "None"
else:
return "/* uh oh: %s */" % ty
@ -4283,6 +4282,10 @@ class CGBindingRoot(CGThing):
'dom::event::*', #XXXjdm
'dom::eventtarget::*', #XXXjdm
'dom::formdata::*', #XXXjdm
'dom::mouseevent::*', #XXXjdm
'dom::uievent::*', #XXXjdm
'dom::windowproxy::*', #XXXjdm
'dom::bindings::codegen::*', #XXXjdm
'script_task::task_from_context',
'dom::bindings::utils::EnumEntry',
'dom::node::ScriptView',

View file

@ -0,0 +1,76 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* For more information on this interface please see
* http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface MouseEvent : UIEvent {
readonly attribute long screenX;
readonly attribute long screenY;
readonly attribute long clientX;
readonly attribute long clientY;
readonly attribute boolean ctrlKey;
readonly attribute boolean shiftKey;
readonly attribute boolean altKey;
readonly attribute boolean metaKey;
readonly attribute unsigned short button;
readonly attribute unsigned short buttons;
readonly attribute EventTarget? relatedTarget;
// Deprecated in DOM Level 3:
[Throws]
void initMouseEvent(DOMString typeArg,
boolean canBubbleArg,
boolean cancelableArg,
WindowProxy? viewArg,
long detailArg,
long screenXArg,
long screenYArg,
long clientXArg,
long clientYArg,
boolean ctrlKeyArg,
boolean altKeyArg,
boolean shiftKeyArg,
boolean metaKeyArg,
unsigned short buttonArg,
EventTarget? relatedTargetArg);
// Introduced in DOM Level 3:
boolean getModifierState(DOMString keyArg);
};
// Event Constructor Syntax:
[Constructor(DOMString typeArg, optional MouseEventInit mouseEventInitDict)]
partial interface MouseEvent
{
};
// Suggested initMouseEvent replacement initializer:
dictionary MouseEventInit {
// Attributes from Event:
boolean bubbles = false;
boolean cancelable = false;
// Attributes from UIEvent:
WindowProxy? view = null;
long detail = 0;
// Attributes for MouseEvent:
long screenX = 0;
long screenY = 0;
long clientX = 0;
long clientY = 0;
boolean ctrlKey = false;
boolean shiftKey = false;
boolean altKey = false;
boolean metaKey = false;
unsigned short button = 0;
// Note: "buttons" was not previously initializable through initMouseEvent!
unsigned short buttons = 0;
EventTarget? relatedTarget = null;
};

View file

@ -0,0 +1,48 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* For more information on this interface please see
* http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface WindowProxy;
interface Node;
[Constructor(DOMString type, optional UIEventInit eventInitDict)]
interface UIEvent : Event
{
readonly attribute WindowProxy? view;
readonly attribute long detail;
void initUIEvent(DOMString aType,
boolean aCanBubble,
boolean aCancelable,
WindowProxy? aView,
long aDetail);
};
// Additional DOM0 properties.
partial interface UIEvent {
const long SCROLL_PAGE_UP = -32768;
const long SCROLL_PAGE_DOWN = 32768;
readonly attribute long layerX;
readonly attribute long layerY;
readonly attribute long pageX;
readonly attribute long pageY;
readonly attribute unsigned long which;
readonly attribute Node? rangeParent;
readonly attribute long rangeOffset;
attribute boolean cancelBubble;
readonly attribute boolean isChar;
};
dictionary UIEventInit : EventInit
{
WindowProxy? view = null;
long detail = 0;
};

View file

@ -25,6 +25,34 @@ impl JSValConvertible for u32 {
}
}
impl JSValConvertible for i32 {
fn to_jsval(&self) -> JSVal {
unsafe {
RUST_UINT_TO_JSVAL(*self as u32)
}
}
fn from_jsval(val: JSVal) -> Option<i32> {
unsafe {
Some(RUST_JSVAL_TO_INT(val) as i32)
}
}
}
impl JSValConvertible for u16 {
fn to_jsval(&self) -> JSVal {
unsafe {
RUST_UINT_TO_JSVAL(*self as u32)
}
}
fn from_jsval(val: JSVal) -> Option<u16> {
unsafe {
Some(RUST_JSVAL_TO_INT(val) as u16)
}
}
}
impl JSValConvertible for bool {
fn to_jsval(&self) -> JSVal {
if *self {

View file

@ -400,7 +400,7 @@ pub struct ConstantSpec {
pub struct DOMClass {
// A list of interfaces that this object implements, in order of decreasing
// derivedness.
interface_chain: [prototypes::id::Prototype, ..2 /*max prototype chain length*/],
interface_chain: [prototypes::id::Prototype, ..3 /*max prototype chain length*/],
unused: bool, // DOMObjectIsISupports (always false)
native_hooks: *NativePropertyHooks
@ -430,6 +430,9 @@ pub mod prototypes {
Event,
EventTarget,
FormData,
UIEvent,
MouseEvent,
WindowProxy,
_ID_Count
}
}
@ -632,7 +635,7 @@ pub extern fn ThrowingConstructor(_cx: *JSContext, _argc: uint, _vp: *JSVal) ->
}
pub fn initialize_global(global: *JSObject) {
let protoArray = @mut ([0 as *JSObject, ..7]); //XXXjdm prototypes::_ID_COUNT
let protoArray = @mut ([0 as *JSObject, ..10]); //XXXjdm prototypes::_ID_COUNT
unsafe {
//XXXjdm we should be storing the box pointer instead of the inner
let box = squirrel_away(protoArray);

View file

@ -0,0 +1,184 @@
/* 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::codegen::MouseEventBinding;
use dom::bindings::utils::{ErrorResult, DOMString};
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
use dom::eventtarget::EventTarget;
use dom::uievent::UIEvent;
use dom::window::Window;
use dom::windowproxy::WindowProxy;
use script_task::{global_script_context};
use js::glue::RUST_OBJECT_TO_JSVAL;
use js::jsapi::{JSObject, JSContext, JSVal};
pub struct MouseEvent {
parent: UIEvent,
screen_x: i32,
screen_y: i32,
client_x: i32,
client_y: i32,
ctrl_key: bool,
shift_key: bool,
alt_key: bool,
meta_key: bool,
button: u16,
related_target: Option<@mut EventTarget>
}
impl MouseEvent {
pub fn new(type_: DOMString, can_bubble: bool, cancelable: bool,
view: Option<@mut WindowProxy>, detail: i32, screen_x: i32,
screen_y: i32, client_x: i32, client_y: i32, ctrl_key: bool,
shift_key: bool, alt_key: bool, meta_key: bool, button: u16,
_buttons: u16, related_target: Option<@mut EventTarget>) -> MouseEvent {
MouseEvent {
parent: UIEvent::new(type_, can_bubble, cancelable, view, detail),
screen_x: screen_x,
screen_y: screen_y,
client_x: client_x,
client_y: client_y,
ctrl_key: ctrl_key,
shift_key: shift_key,
alt_key: alt_key,
meta_key: meta_key,
button: button,
related_target: related_target
}
}
pub fn init_wrapper(@mut self) {
let script_context = global_script_context();
let cx = script_context.js_compartment.cx.ptr;
let owner = script_context.root_frame.get_ref().window;
let cache = owner.get_wrappercache();
let scope = cache.get_wrapper();
self.wrap_object_shared(cx, scope);
}
pub fn Constructor(_owner: @mut Window,
type_: DOMString,
init: &MouseEventBinding::MouseEventInit,
_rv: &mut ErrorResult) -> @mut MouseEvent {
@mut MouseEvent::new(type_, init.bubbles, init.cancelable, init.view, init.detail,
init.screenX, init.screenY, init.clientX, init.clientY,
init.ctrlKey, init.shiftKey, init.altKey, init.metaKey,
init.button, init.buttons, init.relatedTarget)
}
pub fn ScreenX(&self) -> i32 {
self.screen_x
}
pub fn ScreenY(&self) -> i32 {
self.screen_y
}
pub fn ClientX(&self) -> i32 {
self.client_x
}
pub fn ClientY(&self) -> i32 {
self.client_y
}
pub fn CtrlKey(&self) -> bool {
self.ctrl_key
}
pub fn ShiftKey(&self) -> bool {
self.shift_key
}
pub fn AltKey(&self) -> bool {
self.alt_key
}
pub fn MetaKey(&self) -> bool {
self.meta_key
}
pub fn Button(&self) -> u16 {
self.button
}
pub fn Buttons(&self)-> u16 {
//TODO
0
}
pub fn GetRelatedTarget(&self) -> Option<@mut EventTarget> {
self.related_target
}
pub fn GetModifierState(&self, _keyArg: DOMString) -> bool {
//TODO
false
}
pub fn InitMouseEvent(&mut self,
typeArg: DOMString,
canBubbleArg: bool,
cancelableArg: bool,
viewArg: Option<@mut WindowProxy>,
detailArg: i32,
screenXArg: i32,
screenYArg: i32,
clientXArg: i32,
clientYArg: i32,
ctrlKeyArg: bool,
altKeyArg: bool,
shiftKeyArg: bool,
metaKeyArg: bool,
buttonArg: u16,
relatedTargetArg: Option<@mut EventTarget>,
_rv: &mut ErrorResult) {
self.parent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
self.screen_x = screenXArg;
self.screen_y = screenYArg;
self.client_x = clientXArg;
self.client_y = clientYArg;
self.ctrl_key = ctrlKeyArg;
self.alt_key = altKeyArg;
self.shift_key = shiftKeyArg;
self.meta_key = metaKeyArg;
self.button = buttonArg;
self.related_target = relatedTargetArg;
}
}
impl CacheableWrapper for MouseEvent {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
return self.parent.get_wrappercache()
}
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
let mut unused = false;
MouseEventBinding::Wrap(cx, scope, self, &mut unused)
}
}
impl BindingObject for MouseEvent {
fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
self.parent.GetParentObject(cx)
}
}
impl DerivedWrapper for MouseEvent {
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, _vp: *mut JSVal) -> i32 {
fail!(~"nyi")
}
fn wrap_shared(@mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 {
let obj = self.wrap_object_shared(cx, scope);
if obj.is_null() {
return 0;
} else {
unsafe { *vp = RUST_OBJECT_TO_JSVAL(obj) };
return 1;
}
}
}

View file

@ -496,4 +496,13 @@ pub fn define_bindings(compartment: @mut Compartment) {
assert!(codegen::EventTargetBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr,
&mut unused));
assert!(codegen::FormDataBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr,
&mut unused));
assert!(codegen::MouseEventBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr,
&mut unused));
assert!(codegen::UIEventBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr,
&mut unused));
}

View file

@ -0,0 +1,158 @@
/* 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::codegen::UIEventBinding;
use dom::bindings::utils::{ErrorResult, DOMString};
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
use dom::node::{AbstractNode, ScriptView};
use dom::event::Event_;
use dom::window::Window;
use dom::windowproxy::WindowProxy;
use script_task::global_script_context;
use js::glue::RUST_OBJECT_TO_JSVAL;
use js::jsapi::{JSObject, JSContext, JSVal};
pub struct UIEvent {
parent: Event_,
can_bubble: bool,
cancelable: bool,
view: Option<@mut WindowProxy>,
detail: i32
}
impl UIEvent {
pub fn new(type_: DOMString, can_bubble: bool, cancelable: bool,
view: Option<@mut WindowProxy>, detail: i32) -> UIEvent {
UIEvent {
parent: Event_::new(type_),
can_bubble: can_bubble,
cancelable: cancelable,
view: view,
detail: detail
}
}
pub fn init_wrapper(@mut self) {
let script_context = global_script_context();
let cx = script_context.js_compartment.cx.ptr;
let owner = script_context.root_frame.get_ref().window;
let cache = owner.get_wrappercache();
let scope = cache.get_wrapper();
self.wrap_object_shared(cx, scope);
}
pub fn Constructor(_owner: @mut Window,
type_: DOMString,
init: &UIEventBinding::UIEventInit,
_rv: &mut ErrorResult) -> @mut UIEvent {
@mut UIEvent::new(type_, init.parent.bubbles, init.parent.cancelable,
init.view, init.detail)
}
pub fn GetView(&self) -> Option<@mut WindowProxy> {
self.view
}
pub fn Detail(&self) -> i32 {
self.detail
}
pub fn InitUIEvent(&mut self,
type_: DOMString,
can_bubble: bool,
cancelable: bool,
view: Option<@mut WindowProxy>,
detail: i32) {
let mut rv = Ok(());
self.parent.InitEvent(type_, can_bubble, cancelable, &mut rv);
self.can_bubble = can_bubble;
self.cancelable = cancelable;
self.view = view;
self.detail = detail;
}
pub fn LayerX(&self) -> i32 {
//TODO
0
}
pub fn LayerY(&self) -> i32 {
//TODO
0
}
pub fn PageX(&self) -> i32 {
//TODO
0
}
pub fn PageY(&self) -> i32 {
//TODO
0
}
pub fn Which(&self) -> u32 {
//TODO
0
}
pub fn GetRangeParent(&self) -> Option<AbstractNode<ScriptView>> {
//TODO
None
}
pub fn RangeOffset(&self) -> i32 {
//TODO
0
}
pub fn CancelBubble(&self) -> bool {
//TODO
false
}
pub fn SetCancelBubble(&mut self, _val: bool) {
//TODO
}
pub fn IsChar(&self) -> bool {
//TODO
false
}
}
impl CacheableWrapper for UIEvent {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
return self.parent.get_wrappercache()
}
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
let mut unused = false;
UIEventBinding::Wrap(cx, scope, self, &mut unused)
}
}
impl BindingObject for UIEvent {
fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
self.parent.GetParentObject(cx)
}
}
impl DerivedWrapper for UIEvent {
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, _vp: *mut JSVal) -> i32 {
fail!(~"nyi")
}
fn wrap_shared(@mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 {
let obj = self.wrap_object_shared(cx, scope);
if obj.is_null() {
return 0;
} else {
unsafe { *vp = RUST_OBJECT_TO_JSVAL(obj) };
return 1;
}
}
}

View file

@ -0,0 +1,39 @@
/* 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::{CacheableWrapper, WrapperCache};
use script_task::global_script_context;
use js::jsapi::{JSContext, JSObject};
pub struct WindowProxy {
wrapper: WrapperCache
}
impl WindowProxy {
pub fn new() -> @mut WindowProxy {
@mut WindowProxy {
wrapper: WrapperCache::new()
}
}
pub fn init_wrapper(@mut self) {
let script_context = global_script_context();
let cx = script_context.js_compartment.cx.ptr;
let owner = script_context.root_frame.get_ref().window;
let cache = owner.get_wrappercache();
let scope = cache.get_wrapper();
self.wrap_object_shared(cx, scope);
}
}
impl CacheableWrapper for WindowProxy {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
return self.get_wrappercache()
}
fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!("not yet implemented")
}
}

View file

@ -39,8 +39,10 @@ pub mod dom {
pub mod DOMParserBinding;
pub mod EventBinding;
pub mod EventTargetBinding;
pub mod HTMLCollectionBinding;
pub mod FormDataBinding;
pub mod HTMLCollectionBinding;
pub mod MouseEventBinding;
pub mod UIEventBinding;
}
}
pub mod blob;
@ -54,8 +56,11 @@ pub mod dom {
pub mod eventtarget;
pub mod formdata;
pub mod htmlcollection;
pub mod mouseevent;
pub mod node;
pub mod uievent;
pub mod window;
pub mod windowproxy;
}
pub mod html {

View file

@ -57,3 +57,22 @@ window.alert(ev.type);
window.alert(ev.defaultPrevented);
ev.preventDefault();
window.alert(ev.defaultPrevented);
window.alert("MouseEvent:");
window.alert(MouseEvent);
let ev2 = new MouseEvent("press", {bubbles: true, screenX: 150, detail: 100});
window.alert(ev2);
window.alert(ev2.screenX);
window.alert(ev2.detail);
window.alert(ev2.getModifierState("ctrl"));
window.alert(ev2 instanceof Event);
window.alert(ev2 instanceof UIEvent);
//TODO: Doesn't work until we throw proper exceptions instead of returning 0 on
// unwrap failure.
/*try {
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(rects), "length").get.call(window);
window.alert("hmm?");
} catch (x) {
window.alert("ok");
}*/