VAADIN

Google Maps Add-On: Mobile Right-Click for Markers

18 August, 2026

In modern web development, creating a consistent and intuitive user experience across all devices is essential. Users expect features to work seamlessly, whether they’re on a desktop with a mouse or a mobile with touchscreen.

A feature request was presented to us that highlighted a key challenge in this area: bridging the gap between desktop and mobile interactions within our Google Maps Add-On. The request, which can be seen on GitHub, pointed out that while right-clicking a marker is a common action on a desktop, there was no equivalent for touch devices. We embraced the challenge, and after investigation and testing, we came up with a solution. Here’s a look at how we did it.

The Challenge: Bringing Desktop Functionality to Mobile

On a desktop, the right-click is a powerful and universally understood action. It’s not just for menus; it’s a distinct event that developers can use to trigger custom, context-aware functionality. In our Google Maps Add-On, developers can easily hook into this event to create sophisticated interactions.

For example, you might have a marker where a right-click captures the exact coordinates to perform a calculation or checks if the Shift key was held down to trigger a secondary action.

GoogleMapMarker officeMarker = googleMap.addMarker("Our Office",
    new LatLon(-31.620173186615883, -60.67964404821396), false, Markers.PURPLE);

officeMarker.addRightClickListener(e -> {
    String message = "Right-click at lat: " + e.getLatitude();
    if (e.isShiftKey()) {
        message += " (Shift was held down!)";
    }
    Notification.show(message);
});

This works perfectly on a desktop, giving developers access to rich event data. On a mobile device, however, this functionality was previously inaccessible. There is no physical right-click, which was leaving mobile users without access to these advanced, event-driven features.

The Solution: Touch-and-Hold to Simulate a Right-Click

Since version 2.3.0 the add-on automatically detects a “touch-and-hold” gesture on a marker and translates it into a right-click event.

This means the exact same Java code now works perfectly on mobile devices without any changes. A user simply presses and holds their finger on a marker for a moment, and the RightClickListener is triggered, providing the consistent experience they expect.

How It Works: A Look Under the Hood

To make this possible, we’ve implemented logic directly into the Google Maps web-component part. The component listens for a mousedown event, which serves as a universal trigger for both a mouse click and a screen tap.

When this event fires, a short timer begins. If the user holds their press for the duration of the timer (around 800 milliseconds), the component fires the custom right-click event. If they lift their finger or start dragging, the timer is canceled. This ensures the gesture is intentional and provides a smooth, intuitive feel.

Here’s is the main method that was introduced to implement the feature:

/**
   * Sets up touch-and-hold gesture detection to simulate a right-click on mobile devices.
   *
   * The implementation attaches the necessary event listeners to the marker to detect a long press (touch and hold).
   * When a long press is detected, it fires a 'google-map-marker-rightclick' custom event (which the server-side API can listen for).
   * It also handles the cancellation of the gesture if the user moves their finger, releases it too early, or starts dragging the marker.
   * Finally, it prevents a standard 'click' event from firing after a successful long press to avoid duplicate actions. 
   */
  _setupTouchAndHold() {
    // Only enable when clickEvents are on and device is touch/coarse pointer
    const isTouch =
      (typeof navigator !== "undefined" && navigator.maxTouchPoints > 0) ||
      (typeof matchMedia === "function" &&
        matchMedia("(pointer: coarse)").matches);
    if (!this.clickEvents || !isTouch) {
      return; // Skip setup in non-touch environments
    }

    // Avoid double-binding listeners
    if (this._touchHoldInstalled) {
      return;
    }

    // Duration in milliseconds to consider a press a "long press".
    // This value balances being quick enough to feel responsive while being long 
    // enough to prevent accidental triggers. 800ms is a common choice.
    const LONG_PRESS_DURATION = 800;

    // Internal state variables
    this._touchTimer = null; // A timer to track the duration of the press
    this._suppressNextClick = this._suppressNextClick || false; // Flag to suppress the next click event if it follows a long press

    // Listen for 'mousedown', which fires on both desktop clicks and mobile touch-starts
    google.maps.event.addListener(this.marker, "mousedown", (e) => {

      // Respect runtime toggling of clickEvents
      if (!this.clickEvents) {
        return;
      }

      // Ignore secondary button (desktop right-click)
      if (e && e.domEvent && typeof e.domEvent.button === 'number' && e.domEvent.button === 2) {
        return;
      }

      if (this._touchTimer) clearTimeout(this._touchTimer);
      // Start the timer. If it completes, a long press has occurred.
      this._touchTimer = setTimeout(() => {
        // ensure the subsequent synthetic click is swallowed
        this._suppressNextClick = true; 
        // Fire the custom event that simulates a right-click
        this.fire("google-map-marker-rightclick", e);
        // timer consumed
        this._touchTimer = null;
      }, LONG_PRESS_DURATION);
    });

    // Helper function to cancel timer
    const clearTimer = () => {
      if (this._touchTimer) {
        clearTimeout(this._touchTimer);
        this._touchTimer = null;
      }
    };

    // Cancel the timer if the user releases, drags, or moves off the marker
    google.maps.event.addListener(this.marker, "mouseup", clearTimer);
    google.maps.event.addListener(this.marker, "dragstart", clearTimer);
    google.maps.event.addListener(this.marker, "mouseout", clearTimer);

    this._touchHoldInstalled = true;
  },  

});

If you’re still curious, take a look at the whole implementation here.

See It in Action: A Practical Example

The best way to experience this new feature is to try it yourself. And you can use our live demo to see it in action.

Test it live here: Google Maps Add Markers Demo

How to reproduce the behavior:

  1. Navigate to the Add Markers Demo page.
  2. In the options below the map, check the “Right Click” box.
  3. Click the “Add Marker” button. A new marker will appear at the center of the map.
  4. Try it out:
    • On a desktop: Right-click the new marker.
    • On a mobile device: Press and hold your finger on the marker for a moment.

In both cases, a notification will appear displaying the rich event data captured by the listener, including coordinates and any modifier keys used.

The Code Behind the Demo

This functionality is achieved with just a few lines of code in the demo. As you can see from the snippet below, we simply add a RightClickListener to the marker. The add-on now handles all the client-side logic to ensure this single listener works for both desktop and mobile gestures.

// From AddMarkersDemo.java

// ... inside the "Add Marker" button's click listener ...

if (withRightClick.getValue()) {
  marker.addRightClickListener(e -> {
    Div text = new Div(new Text("Alt key: " + e.isAltKey()), new HtmlComponent("br"),
        new Text("Shift key: " + e.isShiftKey()), new HtmlComponent("br"),
        new Text("Ctrol key: " + e.isCtrlKey()), new HtmlComponent("br"),
        new Text("Click counts: " + e.getClickCount()), new HtmlComponent("br"),
        new Text("Latitude: " + e.getLatitude()), new HtmlComponent("br"),
        new Text("Longitude: " + e.getLongitude()));

    Notification notification = new Notification();

    Button closeButton = new Button(new Icon(VaadinIcon.CLOSE_SMALL));
    closeButton.addClickListener(event -> {
      notification.close();
    });

    HorizontalLayout layout = new HorizontalLayout(text, closeButton);
    layout.setAlignItems(Alignment.CENTER);

    notification.add(layout);
    notification.open();
  });
}

Conclusion

Bridging the interaction gap between desktop and mobile is a key step in creating truly universal applications. This update simplifies that challenge by automatically translating touch gestures into the events developers already use. By handling this complexity for you, we make it easier to build rich, interactive mapping features that provide a consistent and reliable experience for every user, on any device.

Hope you find this feature useful. Be sure to explore everything else the Google Maps Add-On has to offer in our centralized demo application. If you have ideas for enhancing this or any other part of the add-on, please let us know by opening an issue on the GitHub repository.

You can find more information about existing versions and supported Vaadin versions on Vaadin’s Directory site. Currently, the add-on is available for Vaadin versions 14, 23, 24 and 25.

Thanks for reading and let’s keep the code flowing!

Paola De Bartolo
By Paola De Bartolo

Systems Engineer. Java Developer. Vaadin enthusiast since the moment I heard "you can implement all UI with Java". Proud member of the #FlowingCodeTeam since 2017.

Join the conversation!