Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8268225: Support :focus-visible and :focus-within CSS pseudoclasses #475

Closed
wants to merge 25 commits into from

Conversation

mstr2
Copy link
Collaborator

@mstr2 mstr2 commented Apr 21, 2021

This PR adds the Node.focusVisible and Node.focusWithin properties, as well as the corresponding :focus-visible and :focus-within CSS pseudo-classes.


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change requires a CSR request to be approved
  • Change must be properly reviewed (2 reviews required, with at least 1 Reviewer, 1 Author)

Issues

  • JDK-8268225: Support :focus-visible and :focus-within CSS pseudoclasses
  • JDK-8274798: Support :focus-visible and :focus-within CSS pseudoclasses (CSR)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jfx pull/475/head:pull/475
$ git checkout pull/475

Update a local copy of the PR:
$ git checkout pull/475
$ git pull https://git.openjdk.org/jfx pull/475/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 475

View PR using the GUI difftool:
$ git pr show -t 475

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/475.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Apr 21, 2021

👋 Welcome back mstr2! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@Maran23
Copy link
Member

Maran23 commented Apr 28, 2021

Do you have a example application or something, where the possible use case/the advantage of this can be shown? I can't imagine right now, where I may want to use that.

@mstr2
Copy link
Collaborator Author

mstr2 commented Apr 28, 2021

Do you have a example application or something, where the possible use case/the advantage of this can be shown? I can't imagine right now, where I may want to use that.

If you are running Windows 10, try opening PC Settings, then go to a section like System > Notifications and actions. There are lots of switches and check boxes that you can toggle, but you'll notice that they don't have any visible focus indicator if you click on them (even tough they are focused after clicking). Only if you press the Tab key you'll see a black border as a visual focus indicator, which will disappear again after clicking.

@mstr2 mstr2 changed the title Support :focus-visible CSS pseudoclass 8268225: Support :focus-visible and :focus-within CSS pseudoclasses Jun 7, 2021
@mstr2 mstr2 marked this pull request as ready for review June 7, 2021 20:53
@openjdk openjdk bot added the rfr Ready for review label Jun 7, 2021
@mlbridge
Copy link

mlbridge bot commented Jun 7, 2021

@kevinrushforth
Copy link
Member

I note that the discussion hasn't finished on the openjfx-dev mailing list as to whether to accept this feature. The proposed API and docs in this PR can be used to inform the discussion, but it's premature to start the code review.

If it ends up going forward, it will need a CSR and 2 reviewers.

/csr
/reviewers 2

@openjdk openjdk bot added the csr Need approved CSR to integrate pull request label Jun 7, 2021
@openjdk
Copy link

openjdk bot commented Jun 7, 2021

@kevinrushforth has indicated that a compatibility and specification (CSR) request is needed for this pull request.
@mstr2 please create a CSR request for issue JDK-8268225. This pull request cannot be integrated until the CSR request is approved.

@openjdk
Copy link

openjdk bot commented Jun 7, 2021

@kevinrushforth
The number of required reviews for this PR is now set to 2 (with at least 1 of role reviewers).

@kevinrushforth kevinrushforth self-requested a review June 9, 2021 12:18
Copy link
Member

@kevinrushforth kevinrushforth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took an initial pass at the API docs. I have a couple global comments.

First, can you reorder the properties and their associated methods such that they are grouped together? If the docs are on the (private) field, which is what we usually do, it should be followed immediately by the associated setter (if any), getter, and property methods.

The order should be:

    /**
     * EXISTING API DOCS FOR FOCUSED PROPERTY
     */
    private FocusPropertyBase focused;

    protected final void setFocused(boolean value) {

    public final boolean isFocused() {

    public final ReadOnlyBooleanProperty focusedProperty() {

    /**
     * API DOCS FOR NEW FOCUSVISIBLE PROPERTY
     */
    private FocusPropertyBase focusVisible;

    public final boolean isFocusVisible() {

    public final ReadOnlyBooleanProperty focusVisibleProperty() {

    ...

Second, the two new properties need both a @defaultValue and an @since NN tag. You can optimistically use @since 17 or you can use @since 18 (the latter is more likely).

@kevinrushforth kevinrushforth self-requested a review June 11, 2021 21:38
Copy link
Member

@kevinrushforth kevinrushforth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API looks reasonable. I left one question inline.

The implementation will take some time to go through. I doubt that this will make JavaFX 17 (which I alluded to earlier). I'm especially curious about some of the patterns that I see, mostly surrounding the FocusPropertyBase implementation class.

  1. FocusPropertyBase overrides set (which is unusual). The current implementation (of FocusedProperty ) has some custom logic as well, but it didn't try to use the set method of a writable property. Also, you use a writable property and don't override invalidated. Can you say why you made the changes you made?
  2. I'm curious about the approach for notifying listeners. It seems similar to what is currently done for focusedProperty, but there are differences. Also, I'm not sure that the two newly added properties need to handle notifications in the same way as focused. I can think of at least one potential issue. If focus shifts from one node to another in the same parent, you might end up notifying a parent's listeners even though its focusWithin is unchanged.
  3. I think the way you are propagating focusWithin might not work if nodes are added or removed from the scene graph.
  4. Normally a read-only property that needs to be settable by the implementation would use ReadOnlyBooleanWrapper. And then the public property method would call getReadOnlyProperty to return the read-only property to the user. The implementation would access the wrapper and you don't need to cast. You could consider having FocusPropertyBase extend ReadOnlyBooleanWrapper.

One thing to consider would be to keep the existing (internal) class for focused and use a more standard ReadOnlyBooleanWrapper class for the two new ones. But maybe there are some implications I haven't thought of yet.

@mstr2
Copy link
Collaborator Author

mstr2 commented Jun 26, 2021

  1. FocusPropertyBase overrides set (which is unusual). The current implementation (of FocusedProperty ) has some custom logic as well, but it didn't try to use the set method of a writable property. Also, you use a writable property and don't override invalidated. Can you say why you made the changes you made?

Technically, it doesn't override set.
FocusPropertyBase extends ReadOnlyBooleanPropertyBase, and also defines a new set method. As implemented, setting the value is completely decoupled from notifying listeners, which leads me directly to your next question...

  1. I'm curious about the approach for notifying listeners. It seems similar to what is currently done for focusedProperty, but there are differences. Also, I'm not sure that the two newly added properties need to handle notifications in the same way as focused. I can think of at least one potential issue. If focus shifts from one node to another in the same parent, you might end up notifying a parent's listeners even though its focusWithin is unchanged.

FocusPropertyBase.set just records the new value, and the decision of whether to notify listeners is deferred until after all focus-related properties have been set on the current node and any of its parents. In the scenario you describe, the recorded value of focusWithin is changed twice, but ends up being the same value as before. In this case, FocusPropertyBase.notifyListeners will not fire a change notification.

There's a test for this scenario: FocusTest.testFocusWithinListenerIsNotInvokedIfPropertyDidNotEffectivelyChange.

  1. I think the way you are propagating focusWithin might not work if nodes are added or removed from the scene graph.

Good point, I'll try to come up with some test cases to see if there are any issues.

  1. Normally a read-only property that needs to be settable by the implementation would use ReadOnlyBooleanWrapper. And then the public property method would call getReadOnlyProperty to return the read-only property to the user. The implementation would access the wrapper and you don't need to cast. You could consider having FocusPropertyBase extend ReadOnlyBooleanWrapper.

That could certainly be an option, although it would increase the memory footprint of Node.
I'm thinking instead to eagerly instantiate all three focus-related properties. In this case, the property field could be referenced directly, which would also remove the need for most casts.

I think that having the same deferred-notification property implementation for all three focus-related properties is the best approach, since the implementation guarantees that listeners are only notified after all changes are committed. At least, I see no upside to not guarantee this. Maybe the atomicity guarantee for focused, focusVisible and focusWithin should be included in the documentation.

@mstr2
Copy link
Collaborator Author

mstr2 commented Jun 18, 2022

@kevinrushforth Do you think this could be a candidate for 19?

@kevinrushforth
Copy link
Member

I'd like to try to get this in for 19, although time is short.

Copy link
Member

@kevinrushforth kevinrushforth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API looks good. I also reviewed the implementation, and it seems fine. I left a few comments inline.

If you still want to get this into JavaFX 19, can you update the CSR as follows?

  1. Change the @since tags from 18 to 19
  2. For the two new properties, please add the two public methods for each property, replacing the "private" field (if you prefer, you can leave the private field as well).
  3. The diffs for cssref.html need to be added to the Specification section.

Once you do that, I will "Review" the CSR, since I am done reviewing the API changes in this PR. You can then Finalize it.

@kevinrushforth
Copy link
Member

One more comment: Have you addressed all questions from @kleopatra ?

@mstr2
Copy link
Collaborator Author

mstr2 commented Jul 7, 2022

I've updated the CSR as requested.

One more comment: Have you addressed all questions from @kleopatra ?

The question was about a parent that is inserted above a focused node in the scene graph. Currently, a focused node remains the focus owner of the scene, even if it is removed from the scene graph in this way. Independent of whether that's a bug, I don't think that question is relevant for this particular PR. We might create a follow-up ticket to investigate the issue and determine whether it's a bug or not.

Copy link
Member

@kevinrushforth kevinrushforth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@kevinrushforth
Copy link
Member

I've updated the CSR as requested.

I just Reviewed it, so go ahead and Finalize it.

One more comment: Have you addressed all questions from @kleopatra ?

The question was about a parent that is inserted above a focused node in the scene graph. Currently, a focused node remains the focus owner of the scene, even if it is removed from the scene graph in this way. Independent of whether that's a bug, I don't think that question is relevant for this particular PR.

I agree.

We might create a follow-up ticket to investigate the issue and determine whether it's a bug or not.

Yes, this sounds like a bug. A follow-up issue seems in order.

@mstr2
Copy link
Collaborator Author

mstr2 commented Jul 8, 2022

I've finalized the CSR.
I hope this PR can attract a timely second review in order to make it into JFX 19.

Copy link
Collaborator

@aghaisas aghaisas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this has baked well.
I have a very minor comment for a missing javadoc tag.

@openjdk openjdk bot removed the csr Need approved CSR to integrate pull request label Jul 11, 2022
@openjdk
Copy link

openjdk bot commented Jul 11, 2022

@mstr2 This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8268225: Support :focus-visible and :focus-within CSS pseudoclasses

Reviewed-by: kcr, aghaisas

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 22 new commits pushed to the master branch:

  • c7d3fd9: 8283402: Update to gcc 11.2 on Linux
  • cbb53b2: 8289952: Visual Studio libs msvcp140_1.dll and msvcp140_2.dll missing from build
  • 187fbe1: 8289381: Fix warnings: The assignment to variable has no effect
  • 60c75b8: 8274771: Map, FlatMap and OrElse fluent bindings for ObservableValue
  • 178d898: 8276056: Control.skin.setSkin(Skin) fails to call dispose() on discarded Skin
  • fc6a602: 8289587: IllegalArgumentException: Color.rgb's red parameter (-16776961) expects color values 0-255
  • 4dcd9e0: 8289171: Blank final field 'dialog' may not have been initialized in scene.control.Dialog:521
  • 28b8220: 8279297: Remove Shape::setMode method
  • 77ecfb7: 8289390: Fix warnings: type parameter E is hiding the type E
  • 704baa3: 8289396: Fix warnings: Null pointer access: The variable instance can only be null at this location
  • ... and 12 more: https://git.openjdk.org/jfx/compare/81e1cc3edcbfda34479ee876cbd9eb74099a7e57...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@kevinrushforth, @aghaisas) but any other Committer may sponsor as well.

➡️ To flag this PR as ready for integration with the above commit message, type /integrate in a new comment. (Afterwards, your sponsor types /sponsor in a new comment to perform the integration).

@openjdk openjdk bot added the ready Ready to be integrated label Jul 11, 2022
@mstr2
Copy link
Collaborator Author

mstr2 commented Jul 11, 2022

/integrate

@openjdk openjdk bot added the sponsor Ready to sponsor label Jul 11, 2022
@openjdk
Copy link

openjdk bot commented Jul 11, 2022

@mstr2
Your change (at version 9a8a838) is now ready to be sponsored by a Committer.

@kevinrushforth
Copy link
Member

/sponsor

@openjdk
Copy link

openjdk bot commented Jul 11, 2022

Going to push as commit 8d5d3ca.
Since your change was applied there have been 24 commits pushed to the master branch:

  • 437c078: 8289255: update Eclipse .classpath and other configuration files
  • 13f3e1f: 8289395: Fix warnings: Varargs methods should only override or be overridden by other varargs methods
  • c7d3fd9: 8283402: Update to gcc 11.2 on Linux
  • cbb53b2: 8289952: Visual Studio libs msvcp140_1.dll and msvcp140_2.dll missing from build
  • 187fbe1: 8289381: Fix warnings: The assignment to variable has no effect
  • 60c75b8: 8274771: Map, FlatMap and OrElse fluent bindings for ObservableValue
  • 178d898: 8276056: Control.skin.setSkin(Skin) fails to call dispose() on discarded Skin
  • fc6a602: 8289587: IllegalArgumentException: Color.rgb's red parameter (-16776961) expects color values 0-255
  • 4dcd9e0: 8289171: Blank final field 'dialog' may not have been initialized in scene.control.Dialog:521
  • 28b8220: 8279297: Remove Shape::setMode method
  • ... and 14 more: https://git.openjdk.org/jfx/compare/81e1cc3edcbfda34479ee876cbd9eb74099a7e57...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Jul 11, 2022
@openjdk openjdk bot closed this Jul 11, 2022
@openjdk openjdk bot removed ready Ready to be integrated rfr Ready for review sponsor Ready to sponsor labels Jul 11, 2022
@openjdk
Copy link

openjdk bot commented Jul 11, 2022

@kevinrushforth @mstr2 Pushed as commit 8d5d3ca.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@mstr2 mstr2 deleted the feature/focusvisible branch January 22, 2023 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integrated Pull request has been integrated
5 participants