From kde-commits Tue May 17 12:46:31 2011 From: Maks Orlovich Date: Tue, 17 May 2011 12:46:31 +0000 To: kde-commits Subject: =?utf-8?q?=5Bkdelibs=5D_khtml=3A_Handle_tabIndex_every_where=2C_?= Message-Id: <20110517124631.50000A60B9 () git ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=130563644510590 Git commit 8fdb65112cb87f07d25433bcfe5a6c9913984277 by Maks Orlovich. Committed on 08/05/2011 at 22:12. Pushed by orlovich into branch 'master'. Handle tabIndex every where, as per ARIA CCBUG: 121572 CCBUG: 158857 M +6 -19 khtml/ecma/kjs_html.cpp M +9 -10 khtml/ecma/kjs_html.h M +4 -2 khtml/html/html_baseimpl.cpp M +1 -1 khtml/html/html_baseimpl.h M +4 -2 khtml/html/html_elementimpl.cpp M +14 -1 khtml/html/html_formimpl.cpp M +2 -4 khtml/html/html_formimpl.h M +6 -0 khtml/html/html_inlineimpl.cpp M +1 -1 khtml/html/html_inlineimpl.h M +5 -25 khtml/svg/SVGAElement.cpp M +1 -3 khtml/svg/SVGAElement.h M +28 -3 khtml/xml/dom_elementimpl.cpp M +4 -2 khtml/xml/dom_elementimpl.h M +13 -3 khtml/xml/dom_nodeimpl.h http://commits.kde.org/kdelibs/8fdb65112cb87f07d25433bcfe5a6c9913984277 diff --git a/khtml/ecma/kjs_html.cpp b/khtml/ecma/kjs_html.cpp index f73f051..826baa1 100644 --- a/khtml/ecma/kjs_html.cpp +++ b/khtml/ecma/kjs_html.cpp @@ -707,6 +707,7 @@ const ClassInfo* KJS::HTMLElement::classInfo() const innerHTML KJS::HTMLElement::ElementInnerHTML DontDelete innerText KJS::HTMLElement::ElementInnerText DontDelete document KJS::HTMLElement::ElementDocument DontDelete|ReadOnly + tabIndex KJS::HTMLElement::ElementTabIndex DontDelete # IE extension children KJS::HTMLElement::ElementChildren DontDelete|ReadOnly all KJS::HTMLElement::ElementAll DontDelete|ReadOnly @@ -804,7 +805,6 @@ const ClassInfo* KJS::HTMLElement::classInfo() const multiple KJS::HTMLElement::SelectMultiple DontDelete name KJS::HTMLElement::SelectName DontDelete size KJS::HTMLElement::SelectSize DontDelete - tabIndex KJS::HTMLElement::SelectTabIndex DontDelete @end @begin HTMLSelectElementProtoTable 4 add KJS::HTMLElement::SelectAdd DontDelete|Function 2 @@ -842,7 +842,6 @@ const ClassInfo* KJS::HTMLElement::classInfo() const readOnly KJS::HTMLElement::InputReadOnly DontDelete size KJS::HTMLElement::InputSize DontDelete src KJS::HTMLElement::InputSrc DontDelete - tabIndex KJS::HTMLElement::InputTabIndex DontDelete type KJS::HTMLElement::InputType DontDelete useMap KJS::HTMLElement::InputUseMap DontDelete value KJS::HTMLElement::InputValue DontDelete @@ -864,7 +863,6 @@ const ClassInfo* KJS::HTMLElement::classInfo() const name KJS::HTMLElement::TextAreaName DontDelete readOnly KJS::HTMLElement::TextAreaReadOnly DontDelete rows KJS::HTMLElement::TextAreaRows DontDelete - tabIndex KJS::HTMLElement::TextAreaTabIndex DontDelete type KJS::HTMLElement::TextAreaType DontDelete|ReadOnly value KJS::HTMLElement::TextAreaValue DontDelete selectionStart KJS::HTMLElement::TextAreaSelectionStart DontDelete @@ -881,7 +879,6 @@ const ClassInfo* KJS::HTMLElement::classInfo() const accessKey KJS::HTMLElement::ButtonAccessKey DontDelete disabled KJS::HTMLElement::ButtonDisabled DontDelete name KJS::HTMLElement::ButtonName DontDelete - tabIndex KJS::HTMLElement::ButtonTabIndex DontDelete type KJS::HTMLElement::ButtonType DontDelete|ReadOnly value KJS::HTMLElement::ButtonValue DontDelete @end @@ -981,7 +978,6 @@ const ClassInfo* KJS::HTMLElement::classInfo() const rev KJS::HTMLElement::AnchorRev DontDelete search KJS::HTMLElement::AnchorSearch DontDelete shape KJS::HTMLElement::AnchorShape DontDelete - tabIndex KJS::HTMLElement::AnchorTabIndex DontDelete target KJS::HTMLElement::AnchorTarget DontDelete text KJS::HTMLElement::AnchorText DontDelete|ReadOnly type KJS::HTMLElement::AnchorType DontDelete @@ -1021,7 +1017,6 @@ const ClassInfo* KJS::HTMLElement::classInfo() const hspace KJS::HTMLElement::ObjectHspace DontDelete name KJS::HTMLElement::ObjectName DontDelete standby KJS::HTMLElement::ObjectStandby DontDelete - tabIndex KJS::HTMLElement::ObjectTabIndex DontDelete type KJS::HTMLElement::ObjectType DontDelete useMap KJS::HTMLElement::ObjectUseMap DontDelete vspace KJS::HTMLElement::ObjectVspace DontDelete @@ -1069,7 +1064,6 @@ const ClassInfo* KJS::HTMLElement::classInfo() const search KJS::HTMLElement::AreaSearch DontDelete|ReadOnly noHref KJS::HTMLElement::AreaNoHref DontDelete shape KJS::HTMLElement::AreaShape DontDelete - tabIndex KJS::HTMLElement::AreaTabIndex DontDelete target KJS::HTMLElement::AreaTarget DontDelete @end @begin HTMLScriptElementTable 7 @@ -1378,7 +1372,6 @@ const KJS::HTMLElement::BoundPropInfo KJS::HTMLElement::bpTable[] = { {ID_SELECT, SelectDisabled, T_Bool, ATTR_DISABLED}, {ID_SELECT, SelectMultiple, T_Bool, ATTR_MULTIPLE}, {ID_SELECT, SelectSize, T_Int, ATTR_SIZE}, //toInt on attr, then number - {ID_SELECT, SelectTabIndex, T_TabIdx, NotApplicable}, {ID_OPTGROUP, OptGroupDisabled, T_Bool, ATTR_DISABLED}, {ID_OPTGROUP, OptGroupLabel, T_String, ATTR_LABEL}, {ID_OPTION, OptionDefaultSelected, T_Bool, ATTR_SELECTED}, @@ -1395,18 +1388,15 @@ const KJS::HTMLElement::BoundPropInfo KJS::HTMLElement::bpTable[] = { {ID_INPUT, InputReadOnly, T_Bool, ATTR_READONLY}, {ID_INPUT, InputSize, T_Int, ATTR_SIZE}, {ID_INPUT, InputSrc, T_URL, ATTR_SRC}, - {ID_INPUT, InputTabIndex, T_TabIdx, NotApplicable}, {ID_INPUT, InputUseMap, T_String, ATTR_USEMAP}, {ID_TEXTAREA, TextAreaAccessKey, T_String, ATTR_ACCESSKEY}, {ID_TEXTAREA, TextAreaCols, T_Int, ATTR_COLS}, {ID_TEXTAREA, TextAreaDisabled, T_Bool, ATTR_DISABLED}, {ID_TEXTAREA, TextAreaReadOnly, T_Bool, ATTR_READONLY}, {ID_TEXTAREA, TextAreaRows, T_Int, ATTR_ROWS}, - {ID_TEXTAREA, TextAreaTabIndex, T_TabIdx, NotApplicable}, {ID_BUTTON, ButtonAccessKey, T_String, ATTR_ACCESSKEY}, {ID_BUTTON, ButtonDisabled, T_Bool , ATTR_DISABLED}, {ID_BUTTON, ButtonName, T_String, ATTR_NAME}, - {ID_BUTTON, ButtonTabIndex, T_TabIdx, NotApplicable}, {ID_BUTTON, ButtonValue, T_String, ATTR_VALUE}, {ID_LABEL, LabelAccessKey, T_String, ATTR_ACCESSKEY}, {ID_LABEL, LabelHtmlFor, T_String, ATTR_FOR}, @@ -1450,7 +1440,6 @@ const KJS::HTMLElement::BoundPropInfo KJS::HTMLElement::bpTable[] = { {ID_A, AnchorRel, T_String, ATTR_REL}, {ID_A, AnchorRev, T_String, ATTR_REV}, {ID_A, AnchorShape, T_String, ATTR_SHAPE}, - {ID_A, AnchorTabIndex, T_Int, ATTR_TABINDEX}, //### not ->tabIndex?? {ID_A, AnchorTarget, T_String, ATTR_TARGET}, {ID_A, AnchorType, T_String, ATTR_TYPE}, {ID_IMG, ImageName, T_String, ATTR_NAME}, @@ -1475,7 +1464,6 @@ const KJS::HTMLElement::BoundPropInfo KJS::HTMLElement::bpTable[] = { {ID_OBJECT, ObjectHspace, T_Int, ATTR_HSPACE}, {ID_OBJECT, ObjectName, T_String, ATTR_NAME}, {ID_OBJECT, ObjectStandby, T_String, ATTR_STANDBY}, - {ID_OBJECT, ObjectTabIndex, T_Int, ATTR_TABINDEX}, //### not element's tabindex? {ID_OBJECT, ObjectType, T_String, ATTR_TYPE}, {ID_OBJECT, ObjectUseMap, T_String, ATTR_USEMAP}, {ID_OBJECT, ObjectVspace, T_Int, ATTR_VSPACE}, @@ -1503,7 +1491,6 @@ const KJS::HTMLElement::BoundPropInfo KJS::HTMLElement::bpTable[] = { {ID_AREA, AreaHref, T_URL, ATTR_HREF}, {ID_AREA, AreaNoHref, T_Bool, ATTR_NOHREF}, {ID_AREA, AreaShape, T_String, ATTR_SHAPE}, - {ID_AREA, AreaTabIndex, T_Int, ATTR_TABINDEX}, {ID_AREA, AreaTarget, T_String, ATTR_TARGET}, {ID_SCRIPT, ScriptHtmlFor, T_Res, NotApplicable}, {ID_SCRIPT, ScriptEvent, T_Res, NotApplicable}, @@ -1649,8 +1636,6 @@ JSValue* KJS::HTMLElement::handleBoundRead(ExecState* exec, int token) const return jsNumber(impl()->getAttribute(prop->attrId).toInt()); case T_URL: return jsString(getURLArg(prop->attrId)); - case T_TabIdx: - return jsNumber(impl()->tabIndex()); case T_Res: return jsString(""); case T_Coll: @@ -2042,6 +2027,8 @@ JSValue* KJS::HTMLElement::getValueProperty(ExecState *exec, int token) const return getHTMLCollection(exec,new HTMLCollectionImpl(&element, HTMLCollectionImpl::DOC_ALL)); else // Enabled but hidden by default return getHTMLCollection(exec,new HTMLCollectionImpl(&element, HTMLCollectionImpl::DOC_ALL), true); + case ElementTabIndex: + return jsNumber(element.tabIndex()); // ### what about style? or is this used instead for DOM2 stylesheets? case ElementContentEditable: return jsString(element.contentEditable()); @@ -2458,9 +2445,6 @@ bool KJS::HTMLElement::handleBoundWrite(ExecState* exec, int token, JSValue* val case T_Bool: impl()->setAttribute(prop->attrId, value->toBoolean(exec) ? "" : 0); return true; - case T_TabIdx: - impl()->setTabIndex(value->toInteger(exec)); - return true; case T_Res: //ignored return true; } @@ -2678,6 +2662,9 @@ void KJS::HTMLElement::putValueProperty(ExecState *exec, int token, JSValue *val case ElementContentEditable: element.setContentEditable(str); return; + case ElementTabIndex: + element.setTabIndex(value->toInteger(exec)); + return; default: kDebug(6070) << "WARNING: KJS::HTMLElement::putValueProperty unhandled token " << token << " thisTag=" << element.tagName().string() << " str=" << str.string(); } diff --git a/khtml/ecma/kjs_html.h b/khtml/ecma/kjs_html.h index c7aace7..6cfcca8 100644 --- a/khtml/ecma/kjs_html.h +++ b/khtml/ecma/kjs_html.h @@ -98,23 +98,23 @@ namespace KJS { BodyOnError, BodyOnMessage, BodyFocus, FormAction, FormEncType, FormElements, FormLength, FormAcceptCharset, FormReset, FormTarget, FormName, FormMethod, FormSubmit, SelectAdd, - SelectTabIndex, SelectValue, SelectSelectedIndex, SelectLength, + SelectValue, SelectSelectedIndex, SelectLength, SelectRemove, SelectForm, SelectType, SelectOptions, SelectDisabled, SelectMultiple, SelectName, SelectSize, SelectItem, OptGroupDisabled, OptGroupLabel, OptionIndex, OptionSelected, OptionForm, OptionText, OptionDefaultSelected, OptionDisabled, OptionLabel, OptionValue, InputReadOnly, InputAccept, - InputSize, InputDefaultValue, InputTabIndex, InputValue, InputType, + InputSize, InputDefaultValue, InputValue, InputType, InputMaxLength, InputDefaultChecked, InputDisabled, InputChecked, InputIndeterminate, InputForm, InputAccessKey, InputAlign, InputAlt, InputName, InputSrc, InputUseMap, InputSelect, InputClick, InputSelectionStart, InputSelectionEnd, InputSetSelectionRange, InputPlaceholder, TextAreaAccessKey, TextAreaName, TextAreaDefaultValue, TextAreaSelect, TextAreaCols, TextAreaDisabled, TextAreaForm, TextAreaType, - TextAreaTabIndex, TextAreaReadOnly, TextAreaRows, TextAreaValue, + TextAreaReadOnly, TextAreaRows, TextAreaValue, TextAreaSelectionStart, TextAreaSelectionEnd, TextAreaSetSelectionRange, TextAreaTextLength, TextAreaPlaceholder, - ButtonClick, ButtonForm, ButtonTabIndex, ButtonName, + ButtonClick, ButtonForm, ButtonName, ButtonDisabled, ButtonAccessKey, ButtonType, ButtonValue, LabelHtmlFor, LabelForm, LabelAccessKey, FieldSetForm, LegendForm, LegendAccessKey, LegendAlign, UListType, UListCompact, OListStart, OListCompact, @@ -126,19 +126,19 @@ namespace KJS { AnchorAccessKey, AnchorCoords, AnchorHref, AnchorProtocol, AnchorHost, AnchorCharset, AnchorHrefLang, AnchorHostname, AnchorType, AnchorPort, AnchorPathName, AnchorHash, AnchorSearch, AnchorName, - AnchorRev, AnchorTabIndex, AnchorTarget, AnchorText, AnchorClick, + AnchorRev, AnchorTarget, AnchorText, AnchorClick, ImageName, ImageAlign, ImageHspace, ImageVspace, ImageUseMap, ImageAlt, ImageLowSrc, ImageWidth, ImageIsMap, ImageBorder, ImageHeight, ImageLongDesc, ImageSrc, ImageX, ImageY, ImageComplete, ObjectHspace, ObjectHeight, ObjectAlign, ObjectBorder, ObjectCode, ObjectType, ObjectVspace, ObjectArchive, ObjectDeclare, ObjectForm, ObjectCodeBase, ObjectCodeType, ObjectData, ObjectGetSVGDocument, - ObjectName, ObjectStandby, ObjectTabIndex, ObjectUseMap, ObjectWidth, ObjectContentDocument, + ObjectName, ObjectStandby, ObjectUseMap, ObjectWidth, ObjectContentDocument, ParamName, ParamType, ParamValueType, ParamValue, AppletArchive, AppletAlt, AppletCode, AppletWidth, AppletAlign, AppletCodeBase, AppletName, AppletHeight, AppletHspace, AppletObject, AppletVspace, MapAreas, MapName, AreaHash, AreaHref, AreaTarget, AreaPort, AreaShape, AreaCoords, AreaAlt, AreaAccessKey, AreaNoHref, AreaHost, AreaProtocol, - AreaHostName, AreaPathName, AreaSearch, AreaTabIndex, ScriptEvent, + AreaHostName, AreaPathName, AreaSearch, ScriptEvent, ScriptType, ScriptHtmlFor, ScriptText, ScriptSrc, ScriptCharset, ScriptDefer, TableSummary, TableTBodies, TableTHead, TableCellPadding, TableDeleteCaption, TableCreateCaption, TableCaption, TableWidth, @@ -168,8 +168,8 @@ namespace KJS { LayerTop, LayerLeft, LayerVisibility, LayerBgColor, LayerClip, LayerDocument, LayerLayers, ElementInnerHTML, ElementTitle, ElementId, ElementDir, ElementLang, ElementClassName, ElementInnerText, ElementDocument, - ElementChildren, ElementContentEditable, ElementIsContentEditable, - ElementAll, ElementScrollIntoView }; + ElementChildren, ElementContentEditable, ElementIsContentEditable, + ElementAll, ElementScrollIntoView, ElementTabIndex }; DOM::HTMLElementImpl* impl() const { return static_cast(m_impl.get()); } JSValue* indexGetter(ExecState *exec, unsigned index); @@ -189,7 +189,6 @@ namespace KJS { T_Bool, //Boolean, return true if property is not null T_Int, T_URL, - T_TabIdx, //Magic tab-index handling T_Res, //Reserved, ignore sets, return empty string T_Coll, //Collection, type is in attrID T_ReadOnly = 0x80 //Property should be handled only on read. diff --git a/khtml/html/html_baseimpl.cpp b/khtml/html/html_baseimpl.cpp index e90b92d..6a65e89 100644 --- a/khtml/html/html_baseimpl.cpp +++ b/khtml/html/html_baseimpl.cpp @@ -453,9 +453,11 @@ void HTMLFrameElementImpl::setLocation( const DOMString& str ) setNeedComputeContent(); // otherwise, request it.. } -bool HTMLFrameElementImpl::isFocusable() const +bool HTMLFrameElementImpl::isFocusableImpl(FocusType ft) const { - return m_render!=0; + if (m_render!=0) + return true; + return HTMLPartContainerElementImpl::isFocusableImpl(ft); } void HTMLFrameElementImpl::setFocus(bool received) diff --git a/khtml/html/html_baseimpl.h b/khtml/html/html_baseimpl.h index 61a27d9..b32034b 100644 --- a/khtml/html/html_baseimpl.h +++ b/khtml/html/html_baseimpl.h @@ -102,7 +102,7 @@ public: bool noResize() { return noresize; } void setLocation( const DOMString& str ); - virtual bool isFocusable() const; + virtual bool isFocusableImpl(FocusType ft) const; virtual void setFocus(bool); DocumentImpl* contentDocument() const; diff --git a/khtml/html/html_elementimpl.cpp b/khtml/html/html_elementimpl.cpp index ba79de3..de0ca30 100644 --- a/khtml/html/html_elementimpl.cpp +++ b/khtml/html/html_elementimpl.cpp @@ -158,8 +158,10 @@ void HTMLElementImpl::parseAttribute(AttributeImpl *attr) break; case ATTR_TABINDEX: indexstring=getAttribute(ATTR_TABINDEX); - if (indexstring.length()) - setTabIndex(indexstring.toInt()); + if (attr->val()) + setTabIndex(attr->value().toInt()); + else + setNoTabIndex(); break; // i18n attributes case ATTR_LANG: diff --git a/khtml/html/html_formimpl.cpp b/khtml/html/html_formimpl.cpp index 07cd035..986f301 100644 --- a/khtml/html/html_formimpl.cpp +++ b/khtml/html/html_formimpl.cpp @@ -1029,8 +1029,11 @@ void HTMLGenericFormElementImpl::setDisabled( bool _disabled ) } } -bool HTMLGenericFormElementImpl::isFocusable() const +bool HTMLGenericFormElementImpl::isFocusableImpl(FocusType ft) const { + if (hasTabIndex()) + return HTMLElementImpl::isFocusableImpl(ft); + if (disabled()) return false; @@ -2073,6 +2076,16 @@ void HTMLLabelElementImpl::attach() HTMLElementImpl::attach(); } + +bool HTMLLabelElementImpl::isFocusableImpl(FocusType ft) const +{ + if (hasTabIndex()) + return HTMLGenericFormElementImpl::isFocusableImpl(ft); + + // We want labels to accept focus on click, but not on tabbing. + return (ft != FT_Tab); +} + NodeImpl* HTMLLabelElementImpl::getFormElement() { const DOMString formElementId = getAttribute(ATTR_FOR); diff --git a/khtml/html/html_formimpl.h b/khtml/html/html_formimpl.h index 9cf9dc1..997d3ec 100644 --- a/khtml/html/html_formimpl.h +++ b/khtml/html/html_formimpl.h @@ -165,9 +165,8 @@ public: bool disabled() const { return m_disabled; } void setDisabled(bool _disabled); - virtual bool isFocusable() const; + virtual bool isFocusableImpl(FocusType ft) const; virtual bool isEnumerable() const { return false; } - virtual bool isDefault() const { return false; } bool readOnly() const { return m_readOnly; } @@ -377,8 +376,7 @@ public: virtual Id id() const; virtual void attach(); virtual void defaultEventHandler(EventImpl *evt); - virtual bool isFocusable() const { return true; } - virtual bool isTabFocusable() const { return false; } + virtual bool isFocusableImpl(FocusType ft) const; NodeImpl* getFormElement(); private: diff --git a/khtml/html/html_inlineimpl.cpp b/khtml/html/html_inlineimpl.cpp index eb7bbc2..172297e 100644 --- a/khtml/html/html_inlineimpl.cpp +++ b/khtml/html/html_inlineimpl.cpp @@ -200,6 +200,12 @@ void HTMLAnchorElementImpl::parseAttribute(AttributeImpl *attr) } } +bool HTMLAnchorElementImpl::isFocusableImpl(FocusType ft) const { + if (m_hasAnchor) + return true; + return HTMLElementImpl::isFocusableImpl(ft); +} + // ------------------------------------------------------------------------- NodeImpl::Id HTMLBRElementImpl::id() const diff --git a/khtml/html/html_inlineimpl.h b/khtml/html/html_inlineimpl.h index 139c762..79a2293 100644 --- a/khtml/html/html_inlineimpl.h +++ b/khtml/html/html_inlineimpl.h @@ -35,7 +35,7 @@ public: HTMLAnchorElementImpl(DocumentImpl *doc) : HTMLElementImpl(doc), m_hasTarget(false) {} - virtual bool isFocusable() const { return m_hasAnchor; } + virtual bool isFocusableImpl(FocusType ft) const; virtual Id id() const; virtual void parseAttribute(AttributeImpl *attr); virtual void defaultEventHandler(EventImpl *evt); diff --git a/khtml/svg/SVGAElement.cpp b/khtml/svg/SVGAElement.cpp index 7f3e8da..5157ae1 100644 --- a/khtml/svg/SVGAElement.cpp +++ b/khtml/svg/SVGAElement.cpp @@ -172,35 +172,15 @@ bool SVGAElement::supportsFocus() const return isFocusable() || (document() && !document()->haveStylesheetsLoaded()); } -bool SVGAElement::isFocusable() const +bool SVGAElement::isFocusableImpl(FocusType ft) const { - if (isContentEditable()) - return SVGStyledTransformableElement::isFocusable(); - - // FIXME: Even if we are not visible, we might have a child that is visible. - // Dave wants to fix that some day with a "has visible content" flag or the like. - if (!renderer() || !(renderer()->style()->visibility() == VISIBLE)) + if (ft == FT_Mouse) return false; - - //khtml FIXME return !renderer()->absoluteClippedOverflowRect().isEmpty(); - return false; -} -bool SVGAElement::isMouseFocusable() const -{ - return false; -} + if (isContentEditable()) + return SVGStyledTransformableElement::isFocusableImpl(ft); -bool SVGAElement::isKeyboardFocusable(DOM::KeyboardEventImpl* event) const -{ - Q_UNUSED(event); - if (!isFocusable()) - return false; - - if (!document()->view()) - return false; - - //khtml FIXME return document()->view()->eventHandler()->tabsToLinks(event); + // TODO: implement focus rules for SVG return false; } diff --git a/khtml/svg/SVGAElement.h b/khtml/svg/SVGAElement.h index 4f745fd..b8d1a25 100644 --- a/khtml/svg/SVGAElement.h +++ b/khtml/svg/SVGAElement.h @@ -54,9 +54,7 @@ namespace WebCore { virtual void defaultEventHandler(Event*); virtual bool supportsFocus() const; - virtual bool isMouseFocusable() const; - virtual bool isKeyboardFocusable(DOM::KeyboardEventImpl*) const; - virtual bool isFocusable() const; + virtual bool isFocusableImpl(FocusType ft) const; virtual bool childShouldCreateRenderer(Node*) const; diff --git a/khtml/xml/dom_elementimpl.cpp b/khtml/xml/dom_elementimpl.cpp index 2a90072..baf0dc9 100644 --- a/khtml/xml/dom_elementimpl.cpp +++ b/khtml/xml/dom_elementimpl.cpp @@ -366,10 +366,11 @@ public: ElementRareDataImpl(); void resetComputedStyle(); short tabIndex() const { return m_tabIndex; } - void setTabIndex(short _tabIndex) { m_tabIndex = _tabIndex; } + void setTabIndex(short _tabIndex) { m_tabIndex = _tabIndex; m_hasTabIndex = true; } RenderStyle* m_computedStyle; signed short m_tabIndex; + bool m_hasTabIndex; }; typedef WTF::HashMap ElementRareDataMap; @@ -386,7 +387,7 @@ static ElementRareDataImpl* rareDataFromMap(const ElementImpl* element) } inline ElementRareDataImpl::ElementRareDataImpl() - : m_computedStyle(0), m_tabIndex(0) + : m_computedStyle(0), m_tabIndex(0), m_hasTabIndex(false) {} void ElementRareDataImpl::resetComputedStyle() @@ -825,6 +826,18 @@ void ElementImpl::setTabIndex(short _tabIndex) createRareData()->setTabIndex(_tabIndex); } +void ElementImpl::setNoTabIndex() +{ + if (!m_elementHasRareData) + return; + rareData()->m_hasTabIndex = false; +} + +bool ElementImpl::hasTabIndex() const +{ + return m_elementHasRareData ? rareData()->m_hasTabIndex : false; +} + void ElementImpl::defaultEventHandler(EventImpl *e) { if (!e->defaultHandled() && document()->part() && e->id() == EventImpl::KEYPRESS_EVENT && e->isKeyRelatedEvent()) { @@ -1023,11 +1036,23 @@ void ElementImpl::recalcStyle( StyleChange change ) setHasChangedChild( false ); } -bool ElementImpl::isFocusable() const +bool ElementImpl::isFocusableImpl(FocusType ft) const { if (m_render && m_render->scrollsOverflow()) return true; + // See WAI-ARIA 1.0, UA implementor's guide, 3.1 for the rules this + // implements. + if (hasTabIndex()) { + int ti = tabIndex(); + + // Negative things are focusable, but not in taborder + if (ti < 0) + return (ft != FT_Tab); + else // ... while everything else is completely focusable + return true; + } + // Only make editable elements selectable if its parent element // is not editable. FIXME: this is not 100% right as non-editable elements // within editable elements are focusable too. diff --git a/khtml/xml/dom_elementimpl.h b/khtml/xml/dom_elementimpl.h index bc611fa..5f33d49 100644 --- a/khtml/xml/dom_elementimpl.h +++ b/khtml/xml/dom_elementimpl.h @@ -209,7 +209,7 @@ public: AttrImpl* getAttributeNodeNS( const DOMString &namespaceURI, const DOMString &localName, int& exceptioncode ); Attr setAttributeNodeNS( AttrImpl* newAttr, int& exceptioncode ); - //Commonly supported extensions + // At this level per WAI-ARIA void blur(); void focus(); @@ -237,6 +237,8 @@ public: virtual short tabIndex() const; void setTabIndex(short _tabIndex); + void setNoTabIndex(); + bool hasTabIndex() const; // DOM methods overridden from parent classes virtual DOMString tagName() const; @@ -330,7 +332,7 @@ public: virtual DOMString toString() const; virtual DOMString selectionToString(NodeImpl *selectionStart, NodeImpl *selectionEnd, int startOffset, int endOffset, bool &found) const; - virtual bool isFocusable() const; + virtual bool isFocusableImpl(FocusType ft) const; virtual bool isContentEditable() const; void setContentEditable(bool enabled); diff --git a/khtml/xml/dom_nodeimpl.h b/khtml/xml/dom_nodeimpl.h index 25a3e04..742d5b3 100644 --- a/khtml/xml/dom_nodeimpl.h +++ b/khtml/xml/dom_nodeimpl.h @@ -265,9 +265,19 @@ public: virtual short tabIndex() const { return 0; } - virtual bool isFocusable() const { return false; } - virtual bool isMouseFocusable() const { return isFocusable(); } - virtual bool isTabFocusable() const { return isFocusable(); } + enum FocusType { + FT_Any, + FT_Mouse, + FT_Tab + }; + + // Elements that are focusable by default should override this. + // Warning: if they're in a language that supports tabIndex (e.g. HTML), + // they must call back to the base class whenever hasTabIndex() is set. + virtual bool isFocusableImpl(FocusType) const { return false; } + bool isFocusable() const { return isFocusableImpl(FT_Any); } + bool isMouseFocusable() const { return isFocusableImpl(FT_Mouse); } + bool isTabFocusable() const { return isFocusableImpl(FT_Tab); } virtual bool isInline() const;