Skip to content
Permalink
Browse files
INPUT_MULTIPLE_FIELDS_UI: Mouse click not on sub-fields in multiple f…
…ields input should not move focus

https://bugs.webkit.org/show_bug.cgi?id=109544

Reviewed by Kentaro Hara.

Source/WebCore:

This is similar to Bug 108914, "Should not move focus if the element
already has focus." We fixed a focus() case in Bug 108914. However we
still have the problem in a case of focusing by mouse click.

The fix for Bug 108914 intercepted focus() function to change the
behavior. However focus-by-click doesn't call focus(), but calls
FocusController::setFocusedNode. To fix this problem, we introduce
oldFocusedNode argument to handleFocusEvent, and
BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent restores the
focus to oldFocusedNode if oldFocusedNode is one of sub-fields.
handleFocusEvent is called whenever the focused node is changed.

We don't need InputType::willCancelFocus any more because the new code
in handleFocusEvent covers it.

Tests: Update fast/forms/time-multiple-fields/time-multiple-fields-focus.html.

* html/HTMLTextFormControlElement.h:
(WebCore::HTMLTextFormControlElement::handleFocusEvent):
Add oldFocusedNode argument.
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::dispatchFocusEvent):
Pass oldFocusedNode to handleFocusEvent.

* html/HTMLInputElement.h:
(HTMLInputElement):
 - Add oldFocusedNode argument to handleFocusEvent.
 - Remove focus() override.
* html/HTMLInputElement.cpp: Remove focus() override.
(WebCore::HTMLInputElement::handleFocusEvent):
Pass oldFocusedNode to InputType::handleFocusEvent.
* html/InputType.cpp: Remove willCancelFocus.
(WebCore::InputType::handleFocusEvent):
Add oldFocusedNode argument.
* html/InputType.h:
(InputType): Ditto.
* html/PasswordInputType.cpp:
(WebCore::PasswordInputType::handleFocusEvent): Ditto.
* html/PasswordInputType.h:
(PasswordInputType): Ditto.

* html/BaseMultipleFieldsDateAndTimeInputType.h:
(BaseMultipleFieldsDateAndTimeInputType):
Remove willCancelFocus, and add oldFocusedNode argument to handleFocusEvent.
* html/BaseMultipleFieldsDateAndTimeInputType.cpp:
(WebCore::BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent):
Pass oldFocusedNode to DateTimeEditElement::focusByOwner if the
direction is FocusDirectionNone.

* html/shadow/DateTimeEditElement.h:
(DateTimeEditElement): Add oldFocusedNode argument to focusByOwner.
* html/shadow/DateTimeEditElement.cpp:
(WebCore::DateTimeEditElement::focusByOwner):
If oldFocusedNode is one of sub-fields, focus on it again.

LayoutTests:

* fast/forms/time-multiple-fields/time-multiple-fields-focus-expected.txt:
* fast/forms/time-multiple-fields/time-multiple-fields-focus.html:
Add test to click a delimiter.


Canonical link: https://commits.webkit.org/127831@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@142592 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
tkent-google committed Feb 12, 2013
1 parent 8712a4b commit 33588627ff5e2dd2b61b40854d9cb9a08ba37930
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 45 deletions.
@@ -1,3 +1,14 @@
2013-02-12 Kent Tamura <tkent@chromium.org>

INPUT_MULTIPLE_FIELDS_UI: Mouse click not on sub-fields in multiple fields input should not move focus
https://bugs.webkit.org/show_bug.cgi?id=109544

Reviewed by Kentaro Hara.

* fast/forms/time-multiple-fields/time-multiple-fields-focus-expected.txt:
* fast/forms/time-multiple-fields/time-multiple-fields-focus.html:
Add test to click a delimiter.

2013-02-11 KwangYong Choi <ky0.choi@samsung.com>

[EFL] Remove webintents from TestExpectations
@@ -3,11 +3,12 @@ Check if focus() for focused input does not change focused sub-field.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


Move focus to the second sub-field, then press Up key:
Move focus to the second sub-field:
PASS document.activeElement is timeInput
PASS timeInput.value is "01:02"
Calls focus(), then press Up key:
PASS timeInput.value is "01:03"
PASS pseudoOfFocused(timeInput) is "-webkit-datetime-edit-minute-field"
PASS timeInput.focus(); pseudoOfFocused(timeInput) is "-webkit-datetime-edit-minute-field"
Click on a delimiter between sub-fields, then check if focused element is not changed:
PASS pseudoOfFocused(timeInput) is "-webkit-datetime-edit-minute-field"
PASS successfullyParsed is true

TEST COMPLETE
@@ -1,26 +1,32 @@
<!DOCTYPE html>
<body>
<script src="../../js/resources/js-test-pre.js"></script>
<input id="timeInput" type="time" value="01:01" autofocus>
<input id="timeInput" type="time" value="01:01" style="font-size:20px" autofocus>
<script>
function dispatchKeyEventTo(type, key, target) {
var event = document.createEvent('KeyboardEvent');
event.initKeyboardEvent(type, true, true, document.defaultView, key);
target.dispatchEvent(event);
}

function pseudoOfFocused() {
return internals.youngestShadowRoot(timeInput).activeElement.getAttribute("pseudo");
}

description('Check if focus() for focused input does not change focused sub-field.');
debug('Move focus to the second sub-field, then press Up key:');
debug('Move focus to the second sub-field:');
var timeInput = document.getElementById('timeInput');
shouldBe('document.activeElement', 'timeInput');
dispatchKeyEventTo('keydown', 'Right', timeInput);
dispatchKeyEventTo('keydown', 'Up', timeInput);
shouldBeEqualToString('timeInput.value', '01:02');
shouldBeEqualToString('pseudoOfFocused(timeInput)', '-webkit-datetime-edit-minute-field');
shouldBeEqualToString('timeInput.focus(); pseudoOfFocused(timeInput)', '-webkit-datetime-edit-minute-field');

debug('Calls focus(), then press Up key:');
timeInput.focus();
dispatchKeyEventTo('keydown', 'Up', timeInput);
shouldBeEqualToString('timeInput.value', '01:03');
debug('Click on a delimiter between sub-fields, then check if focused element is not changed:');
var focusedField = internals.youngestShadowRoot(timeInput).activeElement;
eventSender.mouseMoveTo(focusedField.offsetLeft + focusedField.offsetWidth + 10, focusedField.offsetTop + 10);
eventSender.mouseDown();
eventSender.mouseUp();
shouldBeEqualToString('pseudoOfFocused(timeInput)', '-webkit-datetime-edit-minute-field');
</script>
<script src="../../js/resources/js-test-post.js"></script>
</body>
@@ -1,3 +1,65 @@
2013-02-12 Kent Tamura <tkent@chromium.org>

INPUT_MULTIPLE_FIELDS_UI: Mouse click not on sub-fields in multiple fields input should not move focus
https://bugs.webkit.org/show_bug.cgi?id=109544

Reviewed by Kentaro Hara.

This is similar to Bug 108914, "Should not move focus if the element
already has focus." We fixed a focus() case in Bug 108914. However we
still have the problem in a case of focusing by mouse click.

The fix for Bug 108914 intercepted focus() function to change the
behavior. However focus-by-click doesn't call focus(), but calls
FocusController::setFocusedNode. To fix this problem, we introduce
oldFocusedNode argument to handleFocusEvent, and
BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent restores the
focus to oldFocusedNode if oldFocusedNode is one of sub-fields.
handleFocusEvent is called whenever the focused node is changed.

We don't need InputType::willCancelFocus any more because the new code
in handleFocusEvent covers it.

Tests: Update fast/forms/time-multiple-fields/time-multiple-fields-focus.html.

* html/HTMLTextFormControlElement.h:
(WebCore::HTMLTextFormControlElement::handleFocusEvent):
Add oldFocusedNode argument.
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::dispatchFocusEvent):
Pass oldFocusedNode to handleFocusEvent.

* html/HTMLInputElement.h:
(HTMLInputElement):
- Add oldFocusedNode argument to handleFocusEvent.
- Remove focus() override.
* html/HTMLInputElement.cpp: Remove focus() override.
(WebCore::HTMLInputElement::handleFocusEvent):
Pass oldFocusedNode to InputType::handleFocusEvent.
* html/InputType.cpp: Remove willCancelFocus.
(WebCore::InputType::handleFocusEvent):
Add oldFocusedNode argument.
* html/InputType.h:
(InputType): Ditto.
* html/PasswordInputType.cpp:
(WebCore::PasswordInputType::handleFocusEvent): Ditto.
* html/PasswordInputType.h:
(PasswordInputType): Ditto.

* html/BaseMultipleFieldsDateAndTimeInputType.h:
(BaseMultipleFieldsDateAndTimeInputType):
Remove willCancelFocus, and add oldFocusedNode argument to handleFocusEvent.
* html/BaseMultipleFieldsDateAndTimeInputType.cpp:
(WebCore::BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent):
Pass oldFocusedNode to DateTimeEditElement::focusByOwner if the
direction is FocusDirectionNone.

* html/shadow/DateTimeEditElement.h:
(DateTimeEditElement): Add oldFocusedNode argument to focusByOwner.
* html/shadow/DateTimeEditElement.cpp:
(WebCore::DateTimeEditElement::focusByOwner):
If oldFocusedNode is one of sub-fields, focus on it again.

2013-02-12 Takashi Sakamoto <tasak@google.com>

[Refactoring] Make m_selectorChecker in StyleResolver an on-stack object.
@@ -241,18 +241,15 @@ void BaseMultipleFieldsDateAndTimeInputType::destroyShadowSubtree()
BaseDateAndTimeInputType::destroyShadowSubtree();
}

bool BaseMultipleFieldsDateAndTimeInputType::willCancelFocus(bool restorePreviousSelection, FocusDirection direction)
{
return direction == FocusDirectionNone && m_dateTimeEditElement && m_dateTimeEditElement->hasFocusedField();
}

void BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent(FocusDirection direction)
void BaseMultipleFieldsDateAndTimeInputType::handleFocusEvent(Node* oldFocusedNode, FocusDirection direction)
{
if (!m_dateTimeEditElement)
return;
if (direction == FocusDirectionBackward) {
if (element()->document()->page())
element()->document()->page()->focusController()->advanceFocus(direction, 0);
} else if (direction == FocusDirectionNone) {
m_dateTimeEditElement->focusByOwner(oldFocusedNode);
} else
m_dateTimeEditElement->focusByOwner();
}
@@ -81,9 +81,8 @@ class BaseMultipleFieldsDateAndTimeInputType
virtual void createShadowSubtree() OVERRIDE FINAL;
virtual void destroyShadowSubtree() OVERRIDE FINAL;
virtual void disabledAttributeChanged() OVERRIDE FINAL;
virtual bool willCancelFocus(bool restorePreviousSelection, FocusDirection) OVERRIDE;
virtual void forwardEvent(Event*) OVERRIDE FINAL;
virtual void handleFocusEvent(FocusDirection) OVERRIDE;
virtual void handleFocusEvent(Node* oldFocusedNode, FocusDirection) OVERRIDE;
virtual void handleKeydownEvent(KeyboardEvent*) OVERRIDE FINAL;
virtual bool hasBadInput() const OVERRIDE;
virtual bool hasCustomFocusLogic() const OVERRIDE FINAL;
@@ -370,12 +370,6 @@ void HTMLInputElement::defaultBlur()
HTMLTextFormControlElement::blur();
}

void HTMLInputElement::focus(bool restorePreviousSelection, FocusDirection direction)
{
if (!m_inputType->willCancelFocus(restorePreviousSelection, direction))
HTMLTextFormControlElement::focus(restorePreviousSelection, direction);
}

bool HTMLInputElement::hasCustomFocusLogic() const
{
return m_inputType->hasCustomFocusLogic();
@@ -433,9 +427,9 @@ bool HTMLInputElement::shouldUseInputMethod()
return m_inputType->shouldUseInputMethod();
}

void HTMLInputElement::handleFocusEvent(FocusDirection direction)
void HTMLInputElement::handleFocusEvent(Node* oldFocusedNode, FocusDirection direction)
{
m_inputType->handleFocusEvent(direction);
m_inputType->handleFocusEvent(oldFocusedNode, direction);
}

void HTMLInputElement::handleBlurEvent()
@@ -280,7 +280,6 @@ class HTMLInputElement : public HTMLTextFormControlElement {

virtual void blur() OVERRIDE;
void defaultBlur();
virtual void focus(bool restorePreviousSelection = true, FocusDirection = FocusDirectionNone) OVERRIDE;

virtual const AtomicString& name() const OVERRIDE;

@@ -378,7 +377,7 @@ class HTMLInputElement : public HTMLTextFormControlElement {
virtual void updatePlaceholderText();
virtual bool isEmptyValue() const OVERRIDE { return innerTextValue().isEmpty(); }
virtual bool isEmptySuggestedValue() const { return suggestedValue().isEmpty(); }
virtual void handleFocusEvent(FocusDirection) OVERRIDE;
virtual void handleFocusEvent(Node* oldFocusedNode, FocusDirection) OVERRIDE;
virtual void handleBlurEvent();

virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); }
@@ -88,7 +88,7 @@ void HTMLTextFormControlElement::dispatchFocusEvent(PassRefPtr<Node> oldFocusedN
{
if (supportsPlaceholder())
updatePlaceholderVisibility(false);
handleFocusEvent(direction);
handleFocusEvent(oldFocusedNode.get(), direction);
HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedNode, direction);
}

@@ -127,7 +127,7 @@ class HTMLTextFormControlElement : public HTMLFormControlElementWithState {
// Returns true if suggested value is empty. Used to check placeholder visibility.
virtual bool isEmptySuggestedValue() const { return true; }
// Called in dispatchFocusEvent(), after placeholder process, before calling parent's dispatchFocusEvent().
virtual void handleFocusEvent(FocusDirection) { }
virtual void handleFocusEvent(Node* /* oldFocusedNode */, FocusDirection) { }
// Called in dispatchBlurEvent(), after placeholder process, before calling parent's dispatchBlurEvent().
virtual void handleBlurEvent() { }

@@ -471,11 +471,6 @@ void InputType::blur()
element()->defaultBlur();
}

bool InputType::willCancelFocus(bool, FocusDirection)
{
return false;
}

void InputType::createShadowSubtree()
{
}
@@ -563,7 +558,7 @@ bool InputType::shouldUseInputMethod() const
return false;
}

void InputType::handleFocusEvent(FocusDirection)
void InputType::handleFocusEvent(Node*, FocusDirection)
{
}

@@ -204,7 +204,7 @@ class InputType {
virtual bool isKeyboardFocusable(KeyboardEvent*) const;
virtual bool isMouseFocusable() const;
virtual bool shouldUseInputMethod() const;
virtual void handleFocusEvent(FocusDirection);
virtual void handleFocusEvent(Node* oldFocusedNode, FocusDirection);
virtual void handleBlurEvent();
virtual void accessKeyAction(bool sendMouseEvents);
virtual bool canBeSuccessfulSubmitButton();
@@ -214,7 +214,6 @@ class InputType {
#endif

virtual void blur();
virtual bool willCancelFocus(bool restorePreviousSelection, FocusDirection);

// Shadow tree handling

@@ -95,9 +95,9 @@ bool PasswordInputType::isPasswordField() const
return true;
}

void PasswordInputType::handleFocusEvent(FocusDirection direction)
void PasswordInputType::handleFocusEvent(Node* oldFocusedNode, FocusDirection direction)
{
BaseTextInputType::handleFocusEvent(direction);
BaseTextInputType::handleFocusEvent(oldFocusedNode, direction);
if (element()->document()->frame())
element()->document()->setUseSecureKeyboardEntryWhenActive(true);
}
@@ -50,7 +50,7 @@ class PasswordInputType : public BaseTextInputType {
virtual bool shouldRespectListAttribute() OVERRIDE;
virtual bool shouldRespectSpeechAttribute() OVERRIDE;
virtual bool isPasswordField() const OVERRIDE;
virtual void handleFocusEvent(FocusDirection) OVERRIDE;
virtual void handleFocusEvent(Node* oldFocusedNode, FocusDirection) OVERRIDE;
virtual void handleBlurEvent() OVERRIDE;
};

@@ -509,8 +509,16 @@ void DateTimeEditElement::focusIfNoFocus()
focusOnNextFocusableField(0);
}

void DateTimeEditElement::focusByOwner()
void DateTimeEditElement::focusByOwner(Node* oldFocusedNode)
{
if (oldFocusedNode && oldFocusedNode->isElementNode() && toElement(oldFocusedNode)->isDateTimeFieldElement()) {
DateTimeFieldElement* oldFocusedField = static_cast<DateTimeFieldElement*>(oldFocusedNode);
size_t index = fieldIndexOf(*oldFocusedField);
if (index != invalidFieldIndex && oldFocusedField->isFocusable()) {
oldFocusedField->focus();
return;
}
}
focusOnNextFocusableField(0);
}

@@ -89,7 +89,9 @@ class DateTimeEditElement : public HTMLDivElement, public DateTimeFieldElement::
void disabledStateChanged();
Element* fieldsWrapperElement() const;
void focusIfNoFocus();
void focusByOwner();
// If oldFocusedNode is one of sub-fields, focus on it. Otherwise focus on
// the first sub-field.
void focusByOwner(Node* oldFocusedNode = 0);
bool hasFocusedField();
void readOnlyStateChanged();
void removeEditControlOwner() { m_editControlOwner = 0; }

0 comments on commit 3358862

Please sign in to comment.