﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc
25012	[PATCH] NullPointerException in ParallelWayAction.mouseDragged after JOSM loses focus mid-drag	daredemodaisuki	wangi	"==== What steps will reproduce the problem?

1. Switch to Parallel mode (Shift+P), select a way (or several ways forming a branchless path) and start dragging to create a parallel copy. Keep the left mouse button pressed and drag roughly halfway.
2. Without releasing the button, switch to another window (e.g. trigger screenshot tool by Win+Shift+S, or switch window by Alt+Tab) to let JOSM main window loss focus.
3. Return to JOSM. The parallel-way preview stays frozen at the position where dragging was interrupted, and it no longer follows the mouse.
4. Press and drag again.

==== What is the expected result?

The interrupted drag should be discarded: the tool should return to its normal (not dragging) state, the stale preview should disappear, and the next mouse press should start a clean operation. No exception should be thrown.

==== What happens instead?

A NullPointerException is thrown on the AWT event dispatch thread and JOSM reports an internal error. The parallel-way preview also stays visible and frozen, and a subsequent plain click may unexpectedly clear the selection instead of selecting a way.

==== Please provide any additional information below. Attach a screenshot if possible.

This may caused by ""mode"" and ""pWays"" out of sync.

Normally, the two fields ""mode"" and ""pWays"" must always be consistent (i.e. mode == Mode.DRAGGING implies pWays != null). But if JOSM loses focus when dragging:

1. When the window loses focus during a drag, the mouseReleased event is never delivered, so mouseReleased() is not called. The action therefore stays in the ""dragging"" state forever: mode == Mode.DRAGGING, mouseIsDown == true, mouseHasBeenDragged == true, and pWays still points to the preview object.

2. On the next mousePressed(MouseEvent), the existing pWays is discarded:
       if (pWays != null && pWays.getWays() != null) {
           ... clearSelection(ways);
           pWays = null;
       }
   but mode and mouseIsDown/mouseHasBeenDragged are not reset at this point. Normally this is masked because mouseReleased() resets them, but in this scenario mouseReleased() has already been lost.

3. The subsequent mouseDragged(MouseEvent) passes the checks at the top of the method (mouseIsDown is still true, and the INITIAL_MOVE_DELAY of 200 ms has already elapsed), but the block ""if (mode == Mode.NORMAL) { ... initParallelWays(...) }"" is skipped because mode is still DRAGGING. Execution falls through to:

       ParallelWays.ClosestPoint closest = pWays.closestPoint(enp);   // pWays == null

   which throws:

       java.lang.NullPointerException: Cannot invoke
       ""org.openstreetmap.josm.actions.mapmode.ParallelWays.closestPoint(org.openstreetmap.josm.data.coor.EastNorth)""
       because ""this.pWays"" is null
           at org.openstreetmap.josm.actions.mapmode.ParallelWayAction.mouseDragged(ParallelWayAction.java:407)

So the combination ""mode == DRAGGING while pWays == null"" should be what triggers the crash.

The screenshot tool is just one easy way to lose the mouseReleased event; alt-tabbing, a popup window stealing the button release, or a modal dialog appearing mid-drag should have the same effect.

It might be helpful to reset the whole drag state in mousePressed():

    // before starting a new press, discard any drag that did not end properly
    mouseHasBeenDragged = false;
    if (pWays != null) {
        final List<Way> ways = new ArrayList<>(pWays.getWays());
        ways.removeIf(w -> w.getDataSet() == null);
        getLayerManager().getEditDataSet().clearSelection(ways);
        pWays = null;
        setMode(Mode.NORMAL);          // keep mode consistent with pWays == null
        temporaryLayer.invalidate();   // drop the stale preview
    }

Or to validate the state at the start of mouseDragged():

    if (!mouseIsDown)
        return;
    if (mode == Mode.DRAGGING && pWays == null) { // previous drag did not end properly
        setMode(Mode.NORMAL);
        resetMouseTrackingState();
        return;
    }




{{{
Revision:19678
Build-Date:2026-11-05 12:52:25

Identification: JOSM/1.5 (19678 zh_CN) Windows 10 64-Bit
OS Build number: Windows 10 Home China 22H2 (19045)
Memory Usage: 352 MB / 11808 MB (94 MB allocated, but free)
Java version: 21.0.13+9-LTS, Azul Systems, Inc., OpenJDK 64-Bit Server VM
Look and Feel: com.sun.java.swing.plaf.windows.WindowsLookAndFeel
Screen: \Display0 1920x1080x32bpp@60Hz (scaling 1.00×1.00) \Display1 1080x1920x32bpp@60Hz (scaling 1.00×1.00)
Maximum Screen Size: 1920×1920
Best cursor sizes: 16×16→32×32, 32×32→32×32
System property file.encoding: UTF-8
System property sun.jnu.encoding: GBK
Locale info: zh_CN
Numbers with default locale: 1234567890 -> 1234567890
VM arguments: [-Djpackage.app-version=1.5.19678, -XX:MaxRAMPercentage=75.0, --add-modules=java.scripting,java.sql,javafx.controls,javafx.media,javafx.swing,javafx.web, --add-exports=java.base/sun.security.action=ALL-UNNAMED, --add-exports=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED, --add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED, --add-opens=java.base/java.lang=ALL-UNNAMED, --add-opens=java.base/java.nio=ALL-UNNAMED, --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED, --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED, --add-opens=java.desktop/javax.imageio.spi=ALL-UNNAMED, --add-opens=java.desktop/javax.swing.text.html=ALL-UNNAMED, --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED, -Djpackage.app-path=F:\ExternalAppData\JOSM\JOSM.exe]
Dataset consistency test: No problems found

Plugins:
+ BetterIME (1.2.0)
+ Columbina (1.0.4)
+ FastDraw (36503)
+ MaalausPRO (1.0.0)
+ MakeParallel (v1.1.0)
+ PicLayer (275)
+ RoadRailAlignment (0.2.3)
+ alignways (36493)
+ apache-commons (36483)
+ areaselector (372)
+ austriaaddresshelper (107)
+ buildings_tools (36503)
+ ejml (36483)
+ importvec (36504)
+ laplacian-smooth (4.9.1)
+ log4j (36483)
+ measurement (36503)
+ reverter (36503)
+ shrinkwrap (v1.1.3)
+ splinex (36483)
+ utilsplugin2 (36503)

Tagging presets:
+ https://github.com/OGFlab/name-suggestion-index/raw/main/dist/presets/nsi-josm-presets.xml
+ D:\地图和其它\OGF-Citō\OGF_hx_preset.xml

Map paint styles:
+ https://josm.openstreetmap.de/josmfile?page=Styles/MapWithAI&zip=1
+ https://josm.openstreetmap.de/josmfile?page=Styles/iD&zip=1

Last errors/warnings:
- 00017.077 E: 定位影像“mapmode/maalaus”时失败
- 00069.417 E: Handled by bug report queue: java.lang.NullPointerException: Cannot invoke ""org.openstreetmap.josm.actions.mapmode.ParallelWays.closestPoint(org.openstreetmap.josm.data.coor.EastNorth)"" because ""this.pWays"" is null
- 00069.422 E: Handled by bug report queue: java.lang.NullPointerException: Cannot invoke ""org.openstreetmap.josm.actions.mapmode.ParallelWays.closestPoint(org.openstreetmap.josm.data.coor.EastNorth)"" because ""this.pWays"" is null

OSM API: https://opengeofiction.net/api


=== REPORTED CRASH DATA ===
BugReportExceptionHandler#handleException:
No data collected.

Warning issued by: BugReportExceptionHandler#handleException

=== STACK TRACE ===
Thread: AWT-EventQueue-0 (40) of main
java.lang.NullPointerException: Cannot invoke ""org.openstreetmap.josm.actions.mapmode.ParallelWays.closestPoint(org.openstreetmap.josm.data.coor.EastNorth)"" because ""this.pWays"" is null
	at org.openstreetmap.josm.actions.mapmode.ParallelWayAction.mouseDragged(ParallelWayAction.java:407)
	at java.desktop/java.awt.AWTEventMulticaster.mouseDragged(Unknown Source)
	at java.desktop/java.awt.Component.processMouseMotionEvent(Unknown Source)
	at java.desktop/javax.swing.JComponent.processMouseMotionEvent(Unknown Source)
	at java.desktop/java.awt.Component.processEvent(Unknown Source)
	at java.desktop/java.awt.Container.processEvent(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
}}}
"	defect	assigned	normal	26.12	Core			template_report	
