Skip to content

8389551: Update class docs of MouseEvent - #2238

Open
nlisker wants to merge 2 commits into
openjdk:masterfrom
nlisker:8389551_Update_class_docs_of_MouseEvent
Open

8389551: Update class docs of MouseEvent#2238
nlisker wants to merge 2 commits into
openjdk:masterfrom
nlisker:8389551_Update_class_docs_of_MouseEvent

Conversation

@nlisker

@nlisker nlisker commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Adds a section for button events and clarifies the existing sections.



Progress

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

Issue

  • JDK-8389551: Update class docs of MouseEvent (Enhancement - P4)(⚠️ The fixVersion in this issue is [jfx27] but the fixVersion in .jcheck/conf is jfx28, a new backport will be created when this pr is integrated.)

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 2238

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

Using diff file

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

Using Webrev

Link to Webrev Comment

@bridgekeeper

bridgekeeper Bot commented Aug 1, 2026

Copy link
Copy Markdown

👋 Welcome back nlisker! 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.

@openjdk

openjdk Bot commented Aug 1, 2026

Copy link
Copy Markdown

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@nlisker

nlisker commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Notes to reviewers:

  • I didn't have a touch screen available for this, so I couldn't verify that the parts that talk about touch screens is correct.
  • When testing, I couldn't reproduce the behavior described in the last paragraph for entered/exited events, namely that MOUSE_ENTERED_TARGET and MOUSE_ENTERED can be handled by the same event handler, or that consuming one event stops the other. I didn't try too hard to make it work; I went by what the user will probably try to do. I kept it in this version assuming it's correct somehow.
  • I used the following small tester:
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.InputEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class MouseTest extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(@SuppressWarnings("exports") Stage stage) throws Exception {

        var scene = createScene(createSourcePDR(), createSourceMouseFullPDR(), createSourceDnD(), createTarget());
        stage.setScene(scene);
        stage.show();
    }

    private Rectangle createSourcePDR() {
        var source = new Rectangle(50, 50);
        source.setId("PDR");
        source.setFill(Color.YELLOW);
        source.setOnDragDetected(e -> {
            print(source, e);
            e.consume();
        });
        addCommonListeners(source);
        return source;
    }

    private Rectangle createSourceMouseFullPDR() {
        var source = new Rectangle(50, 50);
        source.setId("FullPDR");
        source.setFill(Color.RED);
        source.setOnDragDetected(e -> {
            source.startFullDrag();
            print(source, e);
            e.consume();
        });
        addCommonListeners(source);
        return source;
    }

    private Rectangle createSourceDnD() {
        var source = new Rectangle(50, 50);
        source.setId("DnD");
        source.setFill(Color.GREEN);
        source.setOnDragDetected(e -> {
            Dragboard db = source.startDragAndDrop(TransferMode.ANY);
            var content = new ClipboardContent();
            content.putString("");
            db.setContent(content);
            print(source, e);
            e.consume();
        });
        addCommonListeners(source);
        return source;
    }

    private Rectangle createTarget() {
        var target = new Rectangle(100, 50);
        target.setId("target");
        target.setFill(Color.BLUE);
        target.setOnDragDetected(MouseEvent::consume);
        addCommonListeners(target);
        return target;
    }

    private Scene createScene(Rectangle sourcePDR, Rectangle sourceFullPDR, Rectangle sourceDrag, Rectangle target) {
        var scene = new Scene(new VBox(10, new HBox(sourcePDR, sourceFullPDR, sourceDrag), target), 300, 200);

        scene.setOnMouseEntered(e -> System.out.println(e.getEventType() + " scene"));
        scene.setOnMouseExited(e -> System.out.println(e.getEventType() + " scene"));

        scene.setOnDragDetected(e -> {
            scene.startFullDrag();
            System.out.println(e.getEventType() + " scene");
        });

        scene.setOnDragDone(e -> {
            e.acceptTransferModes(TransferMode.ANY);
            System.out.println(e.getEventType() + " scene");
        });
        scene.setOnMouseDragReleased(e -> System.out.println(e.getEventType() + " scene"));
        scene.setOnMouseDragDone(e -> System.out.println(e.getEventType() + " scene"));
        return scene;
    }

    private static void addCommonListeners(Node node) {
        // MouseEvent
        node.setOnMouseMoved(e -> print(node, e));
        node.setOnMouseDragged(e -> print(node, e));
        node.setOnMouseEntered(e -> print(node, e));
        node.setOnMouseExited(e -> print(node, e));
        node.setOnMouseReleased(e -> print(node, e));
        node.setOnMouseClicked(e -> print(node, e));
        node.addEventHandler(MouseEvent.MOUSE_ENTERED_TARGET, e -> {
            System.out.print("TARGET_ ");
            print(node, e);
        });

        // MouseDragEvent
        node.setOnMouseDragOver(e -> print(node, e));
        node.setOnMouseDragEntered(e -> print(node, e));
        node.setOnMouseDragExited(e -> print(node, e));
        node.setOnMouseDragReleased(e -> print(node, e));
        node.setOnMouseDragDone(e -> System.out.println(e.getEventType() + " " + node.getId()));

        // DragEvent
        node.setOnDragOver(e -> {
            e.acceptTransferModes(TransferMode.ANY);
            print(node, e);
        });
        node.setOnDragEntered(e -> {
            e.acceptTransferModes(TransferMode.ANY);
            print(node, e);
        });
        node.setOnDragExited(e -> {
            print(node, e);
        });
        node.setOnDragDropped(e -> {
            e.acceptTransferModes(TransferMode.ANY);
            e.setDropCompleted(true);
            print(node, e);
        });
        node.setOnDragDone(e -> {
            e.acceptTransferModes(TransferMode.ANY);
            print(node, e);
        });
    }

    private static void print(Node node, InputEvent e) {
        System.out.println(e.getEventType() + " " + node.getId());
    }
}

@nlisker
nlisker marked this pull request as ready for review August 1, 2026 01:12
@nlisker

nlisker commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

/reviewers 2

@andy-goryachev-oracle @kevinrushforth please review. This is a docs-only change that can go into 27.

@openjdk openjdk Bot added the rfr Ready for review label Aug 1, 2026
@openjdk

openjdk Bot commented Aug 1, 2026

Copy link
Copy Markdown

@nlisker
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 2 (with at least 1 Reviewer, 1 Author).

@mlbridge

mlbridge Bot commented Aug 1, 2026

Copy link
Copy Markdown

Webrevs

@andy-goryachev-oracle andy-goryachev-oracle left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The new diagram is a nice addition (I am not sure if "DRAG_DETECTED" node should be a rhombus since it's a decision node (according to https://en.wikipedia.org/wiki/Flowchart )

The textual changes I like much less, mainly because the old one is more useful, in my opinion, since it describes what actually happens.

/// [mouseTransparent][javafx.scene.Node#mouseTransparentProperty()] set to `true` do not receive mouse events.
///
/// ## Button events
/// A mouse button can be [pressed][#MOUSE_PRESSED] and [released][#MOUSE_RELEASED]. A button [click][#MOUSE_CLICKED]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

it sounds like press-drag-release gesture might produce a MOUSE_CLICKED event. can you clarify?

also, we probably should mention that the MOUSE_CLICKED arrives after the MOUSE_RELEASED, either here or in the MOUSE_CLICKED javadoc.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

it sounds like press-drag-release gesture might produce a MOUSE_CLICKED event. can you clarify?

Both simple PDR and full-PDR can produce MOUSE_CLICKED. Do you want me to explicitly state it? In the section about drag events, it's shown that both end with a release event, so it is implied that it produces a click, but I can add that info.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. click: "A button click occurs after these happen" -> "may follow MOUSE_RELEASED" to be specific. I recall at some point I thought it was press->click->release.

  2. there is no MOUSE_CLICKED in your diagram, plus I can't figure out how a click can be generated during the drag operation.

///
/// There are 3 types of drag gestures that can be chosen from within the `DRAG_DETECTED` handler:
///
/// 1. Simple press-drag-release (PDR), in which the source (picked) node is the only node involved. It receives all the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"node involved" is much more nebulous than "The whole press-drag-release gesture is delivered to one node ... If a mouse clicked event is generated from these events, it is still delivered to the same node." which actually describes what is happening.

I really prefer the old description of the three types, as it is very clear, unlike the new one.

Can we revert?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I fixed the "involved" wording be removing it - the next sentence is specific ("receives all the events in the PDR gesture").

The sentence "If a mouse clicked event is generated from these events, it is still delivered to the same node." is in the next sentence "...including button events even when they occur over other nodes."

The old description is even lacking as it doesn't say that MOUSE_RELEASED events are also delivered to the node. Interestingly, MOUSE_PRESSED events are not generated, I wonder if this is a bug or intended.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the main issue I have with the new version is that it removed some information that I feel is important.

for example:

  • The whole press-drag-release gesture is delivered to one node (removed)
  • and all subsequent mouse events are delivered to that same node until the button is released.
  • If these nodes need to be involved in the gesture, full press-drag-release gesture has to be activated. (instructs what the app dev is supposed to do)

Also, in the new version:

  • DRAG_DETECTED handler: what handler? are you referring to some internal entity?

I think the old Dnd section is much more informative and easier to understand.

Please keep in mind that this is just my opinion, let's see what other people think.

@nlisker

nlisker commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

The new diagram is a nice addition (I am not sure if "DRAG_DETECTED" node should be a rhombus since it's a decision node (according to https://en.wikipedia.org/wiki/Flowchart )

I didn't follow any convention. If it matters, I can adjust the shapes. I assumed it would be clear after reading that section.

The textual changes I like much less, mainly because the old one is more useful, in my opinion, since it describes what actually happens.

I found the old ones to be confusing at best. Some specifics:

  • The methods that start the different drag gestures are not written in the description of each of them; they first appear in the summary, which should be... a summary, not add new information.
  • The summary is long compared to the paragraphs that describe the drag gestures - it's longer than the descriptions of full-PDR and DnD combined. A summary should be short (I turned it into a table).
  • The paragraph that describes full-PDR doesn't start with talking about full-PDR, it continues with (simple) PDR: "During a simple press-drag-release gesture, the other nodes are not involved and don't get any events." (which repeats "The whole press-drag-release gesture is delivered to one node." from its own paragraph). It's not clear that it's supposed to introduce another gesture type.
  • The second paragraph also doesn't say that this is the second gesture type, you get to the DnD paragraph and it starts with "The third gesture type"; where was the second?
  • The DnD paragraph is very terse and doesn't give an example of what it could be used for, unlike the previous paragraphs.

Which lines that describe "what actually happens" are missing? It's probably easier to just add them than just revert.

/// `MOUSE_ENTERED`.
/// 3. During the bubbling phase, its type is switched back to `MOUSE_ENTERED_TARGET`.
///
/// If the event is filtered or consumed, it affects both event types.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how? what happens?

this give very little information.

/// This means that a node can receive these events when the mouse enters a node in its scenegraph hierarchy. To
/// distinguish between these two cases, the event target can be tested on equality with the node.
///
/// Since `MOUSE_ENTERED`/`MOUSE_EXITED` are subtypes of `MOUSE_ENTERED_TARGET`/`MOUSE_EXITED_TARGET`, they are also

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the "subtype" thing is present in the original doc and is quite confusing: aren't those distinct types?
maybe instead we should just rephrase the whole thing saying the *TARGET events are delivered to parents while the ENTERED/EXITED ones to the target node only?

the original phrase "It's still one event just switching types" actually explains the whole thing better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rfr Ready for review

Development

Successfully merging this pull request may close these issues.

2 participants