avm1: Add support for tabEnabled and tabIndex

This commit is contained in:
Kamil Jarosz 2024-03-12 16:23:30 +01:00 committed by Adrian Wielgosik
parent c7b16f4642
commit 9d18bcdd06
3 changed files with 102 additions and 0 deletions

View File

@ -47,6 +47,8 @@ const PROTO_DECLS: &[Declaration] = declare_properties! {
"scale9Grid" => property(button_getter!(scale_9_grid), button_setter!(set_scale_9_grid); DONT_DELETE | DONT_ENUM | VERSION_8);
"filters" => property(button_getter!(filters), button_setter!(set_filters); DONT_DELETE | DONT_ENUM | VERSION_8);
"cacheAsBitmap" => property(button_getter!(cache_as_bitmap), button_setter!(set_cache_as_bitmap); DONT_DELETE | DONT_ENUM | VERSION_8);
// NOTE: `tabEnabled` is not a built-in property of Button.
"tabIndex" => property(button_getter!(tab_index), button_setter!(set_tab_index); VERSION_6);
};
pub fn create_proto<'gc>(
@ -173,3 +175,36 @@ fn set_scale_9_grid<'gc>(
};
Ok(())
}
fn tab_index<'gc>(
this: Avm1Button<'gc>,
_activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(index) = this.tab_index_value() {
Ok(index.into())
} else {
Ok(Value::Undefined)
}
}
fn set_tab_index<'gc>(
this: Avm1Button<'gc>,
activation: &mut Activation<'_, 'gc>,
value: Value<'gc>,
) -> Result<(), Error<'gc>> {
match value {
Value::Undefined | Value::Null => {
this.set_tab_index_value(&mut activation.context, None);
}
Value::Bool(_) | Value::Number(_) => {
// FIXME This coercion is not perfect, as it wraps
// instead of falling back to MIN, as FP does
let i32_value = value.coerce_to_i32(activation)?;
this.set_tab_index_value(&mut activation.context, Some(i32_value));
}
_ => {
this.set_tab_index_value(&mut activation.context, Some(i32::MIN));
}
};
Ok(())
}

View File

@ -116,6 +116,9 @@ const PROTO_DECLS: &[Declaration] = declare_properties! {
"transform" => property(mc_getter!(transform), mc_setter!(set_transform); DONT_ENUM | VERSION_8);
"useHandCursor" => bool(true; DONT_ENUM);
// NOTE: `focusEnabled` is not a built-in property of MovieClip.
// NOTE: `tabEnabled` is not a built-in property of MovieClip.
// NOTE: `tabIndex` is not enumerable in MovieClip, contrary to Button and TextField
"tabIndex" => property(mc_getter!(tab_index), mc_setter!(set_tab_index); DONT_ENUM | VERSION_6);
};
/// Implements `MovieClip`
@ -1819,3 +1822,36 @@ fn set_filters<'gc>(
this.set_filters(activation.context.gc_context, filters);
Ok(())
}
fn tab_index<'gc>(
this: MovieClip<'gc>,
_activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(index) = this.tab_index_value() {
Ok(index.into())
} else {
Ok(Value::Undefined)
}
}
fn set_tab_index<'gc>(
this: MovieClip<'gc>,
activation: &mut Activation<'_, 'gc>,
value: Value<'gc>,
) -> Result<(), Error<'gc>> {
match value {
Value::Undefined | Value::Null => {
this.set_tab_index_value(&mut activation.context, None);
}
Value::Bool(_) | Value::Number(_) => {
// FIXME This coercion is not perfect, as it wraps
// instead of falling back to MIN, as FP does
let i32_value = value.coerce_to_i32(activation)?;
this.set_tab_index_value(&mut activation.context, Some(i32_value));
}
_ => {
this.set_tab_index_value(&mut activation.context, Some(i32::MIN));
}
};
Ok(())
}

View File

@ -93,6 +93,8 @@ const PROTO_DECLS: &[Declaration] = declare_properties! {
"gridFitType" => property(tf_getter!(grid_fit_type), tf_setter!(set_grid_fit_type));
"sharpness" => property(tf_getter!(sharpness), tf_setter!(set_sharpness));
"thickness" => property(tf_getter!(thickness), tf_setter!(set_thickness));
// NOTE: `tabEnabled` is not a built-in property of TextField.
"tabIndex" => property(tf_getter!(tab_index), tf_setter!(set_tab_index); VERSION_6);
};
/// Implements `TextField`
@ -113,6 +115,7 @@ pub fn create_proto<'gc>(
define_properties_on(PROTO_DECLS, context, object, fn_proto);
object.into()
}
pub fn password<'gc>(
this: EditText<'gc>,
_activation: &mut Activation<'_, 'gc>,
@ -911,3 +914,31 @@ fn set_restrict<'gc>(
};
Ok(())
}
pub fn tab_index<'gc>(
this: EditText<'gc>,
_activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(index) = this.tab_index_value() {
Ok(index.into())
} else {
Ok(Value::Undefined)
}
}
pub fn set_tab_index<'gc>(
this: EditText<'gc>,
activation: &mut Activation<'_, 'gc>,
value: Value<'gc>,
) -> Result<(), Error<'gc>> {
match value {
Value::Undefined | Value::Null => {
this.set_tab_index_value(&mut activation.context, None);
}
_ => {
let u32_value = value.coerce_to_u32(activation)?;
this.set_tab_index_value(&mut activation.context, Some(u32_value));
}
};
Ok(())
}