flow icon indicating copy to clipboard operation
flow copied to clipboard

Implement ClickEvent.getRelativeX() and getRelativeY() methods

Open Copilot opened this issue 8 months ago β€’ 6 comments

Adds relative coordinate methods to ClickEvent that provide mouse coordinates relative to the clicked component, restoring functionality that was available in Vaadin 8's MouseEvents.getRelativeY().

Problem

Vaadin 23's ClickEvent only provides screenX/Y (relative to screen) and clientX/Y (relative to viewport) coordinates. There was no way to get coordinates relative to the clicked component itself, which is essential for components like scrollbars, drawing areas, and overview maps where precise positioning within the component matters.

The current workaround required additional server roundtrips:

div.addClickListener(e -> {
  div.getElement().executeJs("return this.getBoundingClientRect().top;").then(Double.class, viewportY ->
    Notification.show("" + (e.clientY - viewportY)"));
});

Solution

Added getRelativeX() and getRelativeY() methods that calculate coordinates relative to the component's top-left corner using client-side JavaScript expressions:

div.addClickListener(event -> {
    int relativeX = event.getRelativeX(); // Position within the component
    int relativeY = event.getRelativeY(); // Position within the component
    // Perfect for scrollbar controls, drawing components, etc.
});

Implementation Details

  • Zero performance overhead: Coordinates calculated during event processing using @EventData annotations
  • Client-side calculation: Uses element.getBoundingClientRect() to determine component position
  • Consistent API: Follows same pattern as existing getClientX/Y() and getScreenX/Y() methods
  • Backward compatible: All existing code continues to work unchanged

Changes Made

  • Added relativeX and relativeY fields to ClickEvent
  • Updated constructor with @EventData annotations using JavaScript expressions:
    • event.clientX - element.getBoundingClientRect().left for relativeX
    • event.clientY - element.getBoundingClientRect().top for relativeY
  • Added getRelativeX() and getRelativeY() getter methods with proper Javadoc
  • Comprehensive test coverage for both server-side and client-side constructors
  • Demo view showing all coordinate types in action

This directly addresses the customer use case mentioned in the issue - building scrollbar-like components and overview maps that need precise positioning within the component area.

Fixes #20488.

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • maven.vaadin.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.10/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.10/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.10 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.10/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/flow/flow org.codehaus.plexus.classworlds.launcher.Launcher -q test-compile -pl flow-server (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.10/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.10/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.10 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.10/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/flow/flow org.codehaus.plexus.classworlds.launcher.Launcher -q compile -Dmaven.test.skip=true (dns block)

If you need me to access, download, or install something from one of these locations, you can either:


πŸ’‘ You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot avatar Jul 01 '25 11:07 Copilot

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Jul 01 '25 11:07 CLAassistant

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • maven.vaadin.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.10/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.10/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.10 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.10/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/flow/flow org.codehaus.plexus.classworlds.launcher.Launcher test -Dtest=ClickEventTest -pl flow-server (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot avatar Jul 01 '25 12:07 Copilot

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses

I tried to connect to the following addresses, but was blocked by firewall rules:

  • maven.vaadin.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.10/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.10/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.10 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.10/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/flow/flow org.codehaus.plexus.classworlds.launcher.Launcher -q compile test-compile -pl flow-tests/test-root-context (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot avatar Jul 01 '25 12:07 Copilot

Test Results

1β€ˆ049 files   -β€Š257  1β€ˆ049 suites   -β€Š257   1h 3m 27s ⏱️ - 13m 17s 8β€ˆ555 tests  -β€Š616  8β€ˆ012 βœ…  -β€Š1β€ˆ092  63 πŸ’€  -β€Šβ€‡4  51 ❌ +51  429 πŸ”₯ +429  8β€ˆ646 runsβ€Š  -β€Š987  8β€ˆ021 βœ…  -β€Š1β€ˆ537  58 πŸ’€  -β€Š17  73 ❌ +73  494 πŸ”₯ +494 

For more details on these failures and errors, see this check.

Results for commit 55056810. ± Comparison against base commit 61ea69f1.

This pull request removes 621 and adds 5 tests. Note that renamed tests count towards both.
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplate
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplateWithComments_commentsProperlyIgnored
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplate_codeInRenderBeforeHtml_templateProperlyParsed
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplate_codeWithHtmlAfterRender_templateProperlyParsed
com.vaadin.flow.component.littemplate.BundleLitParserTest ‑ parseTemplate_codeWithHtmlBeforeRender_templateProperlyParsed
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_disabled_exceptionIsThrown
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_setAttributeBinding_attributeIsIgnored
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_setClass_classIsSetAsAttribute
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_setDynamicValue_attributeIsIgnored
com.vaadin.flow.component.littemplate.InjectableLitElementInitializerTest ‑ initializeElement_setHref_hrefIsSetAsAttribute
…
com.vaadin.flow.component.ClickEventTest ‑ clientSideConstructor
com.vaadin.flow.component.ClickEventTest ‑ oldClientSideConstructorBackwardCompatibility
com.vaadin.flow.component.ClickEventTest ‑ relativeCoordinatesAreDistinctFromOtherCoordinates
com.vaadin.flow.component.ClickEventTest ‑ serverSideConstructor
com.vaadin.flow.uitest.ui.RelativeCoordinatesIT ‑ clickShowsRelativeCoordinates[any_Chrome_]

:recycle: This comment has been updated with latest results.

github-actions[bot] avatar Jul 01 '25 14:07 github-actions[bot]

Format Checker Report

BLOCKER There are 4 files with format errors

  • To see a complete report of formatting issues, download the differences artifact

  • To fix the build, please run mvn spotless:apply in your branch and commit the changes.

  • Optionally you might add the following line in your .git/hooks/pre-commit file:

    mvn spotless:apply
    

Here is the list of files with format issues in your PR:

flow-server/src/main/java/com/vaadin/flow/component/ClickEvent.java
flow-server/src/test/java/com/vaadin/flow/component/ClickEventTest.java
flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/RelativeCoordinatesView.java
flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/RelativeCoordinatesIT.java

github-actions[bot] avatar Dec 08 '25 12:12 github-actions[bot]