<AWT Dev> [10] Review request for 8155197: Focus transition issue
Semyon Sadetsky
semyon.sadetsky at oracle.com
Thu Oct 5 21:45:55 UTC 2017
OK, looks good to me, thanks.
--Semyon
On 10/05/2017 02:15 PM, Dmitry Markov wrote:
> Hi Semyon,
>
>> On 5 Oct 2017, at 17:13, Semyon Sadetsky <semyon.sadetsky at oracle.com
>> <mailto:semyon.sadetsky at oracle.com>> wrote:
>>
>> Hi Dmitriy,
>>
>> On 10/05/2017 07:25 AM, Dmitry Markov wrote:
>>> Hi Semyon,
>>>
>>> Actually the most recent focus owner is updated during invocation of
>>> setEnabled(), setFocusable() and setVisible(). Please find the
>>> details below:
>>> - Component.setEnabled(false), (i.e. disable a component) -
>>> setEnabled(false) -> Component.this.setEnabled(false) ->
>>> enable(false) -> disable() ->
>>> KeyboardFocusManager.clearMostRecentFocusOwner()
>>> - Component.setFocusable(false), (i.e. make a component
>>> non-focusable) - setFocusable(false) -> transferFocus()
>>> and KeyboardFocusManager.clearMostRecentFocusOwner()
>>> - Component.setVisible(false), (i.e. make a component invisible) -
>>> setVisible(false) -> Component.this.setVisible(false) -> show(false)
>>> -> hide() -> clearMostRecentFocusOwnerOnHide() and transferFocus()
>>>
>>> So the most recent focus owner is always up to date. I am sorry, but
>>> looks like it is not necessary to perform checks such as isShowing()
>>> and canBeFocusOwner() before we set some value to restoreFocusTo.
>>> These checks are implicitly performed before usage of restoreFocusTo
>>> and I believe that is enough even for concurrent execution. What do
>>> you think?
>>
>> Yes, this makes sense. I'm only not sure about the case when a parent
>> component is made invisible and the most recent focus owner is
>> cleared for the parent component but not for its child components. So
>> all the child components will start to return isShowing() false (e.g.
>> non-focusable) but any of them still may be set as most recent focus
>> owner. This makes the isShowing() check mandatory for component
>> returned by getMostRecentFocusOwner().
>>
> If a parent component, (i.e. container) is made invisible, the most
> recent focus owner is cleared for its child components too, see
> implementation of clearMostRecentFocusOwnerOnHide() in Container class
> for details. So I do not think that it is really necessary to invoke
> isShowing() for the component returned by getMostRecentFocusOwner().
>
> Thanks,
> Dmitry
>>
>> --Semyon
>>>
>>> Thanks,
>>> Dmitry
>>>> On 4 Oct 2017, at 17:23, Semyon Sadetsky
>>>> <semyon.sadetsky at oracle.com <mailto:semyon.sadetsky at oracle.com>> wrote:
>>>>
>>>> Hi Dmitry,
>>>>
>>>> If you make a detailed look on the Component class methods like
>>>> setEnables(), setFocusable() and setVisible() the most recent focus
>>>> owner is cleared or transferred only after the component is made
>>>> non-focusable. Since the fix is aimed for concurrent scenarios the
>>>> recheck actually makes sens.
>>>>
>>>> Also it would be more correct always trying to determine the first
>>>> focusable component in traversal order before before the attempt to
>>>> set focus owner as it is done in restoreFocus(Window aWindow,
>>>> Component boolean clearOnFailure):
>>>>
>>>> if (!toFocus.isShowing() ||
>>>> !toFocus.canBeFocusOwner()) {
>>>> toFocus = toFocus.getNextFocusCandidate();
>>>> }
>>>> otherwise when focus is restored to actually non-focusable
>>>> component the final focus owner may become null while the next
>>>> component in container traversal order is expected to have the
>>>> input focus.
>>>>
>>>> --Semyon
>>>>
>>>>
>>>> On 10/04/2017 03:25 AM, Dmitry Markov wrote:
>>>>> Hi Sergey,
>>>>>
>>>>> Good catch!
>>>>> Actually we check restoreFocusTo before its usage, (i.e. we
>>>>> compare restoreFocusTo with most resent focus owner for the
>>>>> window; most recent focus owner is visible and focusable,
>>>>> otherwise it is removed from recent focus owners map).
>>>>> So the checks before assignment are not really necessary. I
>>>>> updated the fix (reverted it to the previous version). Please find
>>>>> webrev here:
>>>>> http://cr.openjdk.java.net/~dmarkov/8155197/webrev.03/
>>>>> <http://cr.openjdk.java.net/%7Edmarkov/8155197/webrev.03/>
>>>>>
>>>>> Thanks,
>>>>> Dmitry
>>>>>> On 3 Oct 2017, at 18:30, Sergey Bylokhov
>>>>>> <sergey.bylokhov at oracle.com <mailto:sergey.bylokhov at oracle.com>>
>>>>>> wrote:
>>>>>>
>>>>>> Hi, Dmitry.
>>>>>> If this check is valid then probably the same check should be
>>>>>> added to restoreFocus()? before:
>>>>>> #173 restoreFocusTo = toFocus;
>>>>>>
>>>>>> But as it was mentioned before, the component can become
>>>>>> non-visible/non-focusable at any point, for example after this
>>>>>> check but before the assignment. And instead of data validation
>>>>>> before assignment we should check them before use. As far as I
>>>>>> understand we already do this, all usages of restoreFocusTo are a
>>>>>> checks == or != to some other component which is visible and
>>>>>> focusable, isn't it?
>>>>>>
>>>>>> On 10/3/17 08:23, Dmitry Markov wrote:
>>>>>>> Hi Semyon,
>>>>>>> I have updated the fix based on your suggestion. The new version
>>>>>>> is located
>>>>>>> athttp://cr.openjdk.java.net/~dmarkov/8155197/webrev.02/
>>>>>>> <http://cr.openjdk.java.net/%7Edmarkov/8155197/webrev.02/>
>>>>>>> Also I slightly modified the test to simplify it.
>>>>>>> Thanks,
>>>>>>> Dmitry
>>>>>>>> On 2 Oct 2017, at 18:32, Semyon Sadetsky
>>>>>>>> <semyon.sadetsky at oracle.com
>>>>>>>> <mailto:semyon.sadetsky at oracle.com><mailto:semyon.sadetsky at oracle.com>>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>> Hi Dmitry,
>>>>>>>>
>>>>>>>>>> Actually the parent frame doesn't own the input focus when
>>>>>>>>>> the issue happens. The focus is on the dialog already and
>>>>>>>>>> when FOCUS_GAINED event comes for the dialog the KFM
>>>>>>>>>> discovers that the dialog should not have the focus and
>>>>>>>>>> rejects it in line 588 of the DefaultKeyboardFocusManager:
>>>>>>>>>>
>>>>>>>>>> restoreFocus(fe, newFocusedWindow);
>>>>>>>>>>
>>>>>>>>>> This happens when the dialog became non-focusable
>>>>>>>>>> (non-visible) after the focus request is sent, but before the
>>>>>>>>>> corresponding FOCUS_GAINED event is handled on the EDT. In
>>>>>>>>>> this case the focus is directly restored to the previously
>>>>>>>>>> focused window which doesn't have the focus at this moment
>>>>>>>>>> and input focus cannot be requested to one of its components
>>>>>>>>>> synchronously.
>>>>>>>>>> Please confirm whether you agree on the root cause of the bug.
>>>>>>>>>>
>>>>>>>>> You are right. I agree with your evaluation.
>>>>>>>> Thanks.
>>>>>>>> Before setting the restoreFocusTo to toFocus in line 190 I
>>>>>>>> would recheck for toFocus.isShowing() &&
>>>>>>>> toFocus.canBeFocusOwner() once again because the component can
>>>>>>>> be made non-focusable concurrently.
>>>>>>>>
>>>>>>>> --Semyon
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Best regards, Sergey.
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/awt-dev/attachments/20171005/d8f07b8e/attachment-0001.html>
More information about the awt-dev
mailing list