From 82c7606f3d93bd38b9fea37f5ee61ba37e1ac06c Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Tue, 30 Jul 2024 11:24:25 -0700 Subject: [PATCH 01/10] propagate consume action --- .../src/main/java/javafx/event/Event.java | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/modules/javafx.base/src/main/java/javafx/event/Event.java b/modules/javafx.base/src/main/java/javafx/event/Event.java index 03d898ccb5e..644c5c59d9f 100644 --- a/modules/javafx.base/src/main/java/javafx/event/Event.java +++ b/modules/javafx.base/src/main/java/javafx/event/Event.java @@ -25,11 +25,11 @@ package javafx.event; -import java.util.EventObject; - -import com.sun.javafx.event.EventUtil; import java.io.IOException; +import java.util.EventObject; import javafx.beans.NamedArg; +import javafx.beans.property.SimpleBooleanProperty; +import com.sun.javafx.event.EventUtil; // PENDING_DOC_REVIEW /** @@ -68,7 +68,7 @@ public class Event extends EventObject implements Cloneable { /** * Whether this event has been consumed by any filter or handler. */ - protected boolean consumed; + private SimpleBooleanProperty consumed; /** * Construct a new {@code Event} with the specified event type. The source @@ -132,8 +132,9 @@ public Event copyFor(final Object newSource, final EventTarget newTarget) { newEvent.source = (newSource != null) ? newSource : NULL_SOURCE_TARGET; newEvent.target = (newTarget != null) ? newTarget : NULL_SOURCE_TARGET; - newEvent.consumed = false; - + // cloning does not clone properties + newEvent.consumed = null; + newEvent.consumedProperty().bindBidirectional(consumedProperty()); return newEvent; } @@ -144,15 +145,22 @@ public Event copyFor(final Object newSource, final EventTarget newTarget) { * @return {@code true} if this {@code Event} has been consumed, * {@code false} otherwise */ - public boolean isConsumed() { - return consumed; + public final boolean isConsumed() { + return consumed == null ? false : consumed.get(); } /** * Marks this {@code Event} as consumed. This stops its further propagation. */ - public void consume() { - consumed = true; + public final void consume() { + consumedProperty().set(true); + } + + private final SimpleBooleanProperty consumedProperty() { + if (consumed == null) { + consumed = new SimpleBooleanProperty(); + } + return consumed; } /** From 517092192743af3b85a3412a8ed12299c55ce30c Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Tue, 30 Jul 2024 12:16:33 -0700 Subject: [PATCH 02/10] copy for test --- .../src/main/java/com/sun/javafx/event/EventUtil.java | 2 +- .../javafx.base/src/main/java/javafx/event/Event.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java index 10f9fa05a2b..1ea5db8ed35 100644 --- a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java +++ b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java @@ -40,7 +40,7 @@ public final class EventUtil { public static Event fireEvent(EventTarget eventTarget, Event event) { if (event.getTarget() != eventTarget) { - event = event.copyFor(event.getSource(), eventTarget); + event = event.copyForTest(event.getSource(), eventTarget); } if (eventDispatchChainInUse.getAndSet(true)) { diff --git a/modules/javafx.base/src/main/java/javafx/event/Event.java b/modules/javafx.base/src/main/java/javafx/event/Event.java index 644c5c59d9f..d8e7d471488 100644 --- a/modules/javafx.base/src/main/java/javafx/event/Event.java +++ b/modules/javafx.base/src/main/java/javafx/event/Event.java @@ -137,6 +137,16 @@ public Event copyFor(final Object newSource, final EventTarget newTarget) { newEvent.consumedProperty().bindBidirectional(consumedProperty()); return newEvent; } + // TODO hide behind the accessor + public Event copyForTest(final Object newSource, final EventTarget newTarget) { + final Event newEvent = (Event) clone(); + + newEvent.source = (newSource != null) ? newSource : NULL_SOURCE_TARGET; + newEvent.target = (newTarget != null) ? newTarget : NULL_SOURCE_TARGET; + // cloning does not clone properties + newEvent.consumed = null; + return newEvent; + } /** * Indicates whether this {@code Event} has been consumed by any filter or From a3519c94924fa2ca295fb97587b1829e0b417abe Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Tue, 30 Jul 2024 13:00:57 -0700 Subject: [PATCH 03/10] event helper --- .../com/sun/javafx/event/EventHelper.java | 63 +++++++++++++++++++ .../java/com/sun/javafx/event/EventUtil.java | 4 +- .../src/main/java/javafx/event/Event.java | 22 ++++--- 3 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java diff --git a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java new file mode 100644 index 00000000000..1d335347a77 --- /dev/null +++ b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.javafx.event; + +import javafx.event.Event; +import javafx.event.EventTarget; + +/** + * Provides access to private methods in Event. + */ +public class EventHelper { + static { + // copied from com.sun.javafx.util.Utils in javafx.graphics; + try { + Class c = Event.class; + Class.forName(c.getName(), true, c.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); // Can't happen + } + } + + public interface Accessor { + public Event copyForTest(Event ev, Object newSource, EventTarget newTarget); + } + + private static Accessor accessor; + + private EventHelper() { + } + + public static void setAccessor(Accessor a) { + if (accessor != null) { + throw new IllegalStateException(); + } + accessor = a; + } + + public static Event copyForTest(Event ev, Object newSource, EventTarget newTarget) { + return accessor.copyForTest(ev, newSource, newTarget); + } +} diff --git a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java index 1ea5db8ed35..b98895a5fc2 100644 --- a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java +++ b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ public final class EventUtil { public static Event fireEvent(EventTarget eventTarget, Event event) { if (event.getTarget() != eventTarget) { - event = event.copyForTest(event.getSource(), eventTarget); + event = EventHelper.copyForTest(event, event.getSource(), eventTarget); } if (eventDispatchChainInUse.getAndSet(true)) { diff --git a/modules/javafx.base/src/main/java/javafx/event/Event.java b/modules/javafx.base/src/main/java/javafx/event/Event.java index d8e7d471488..9423c2482ee 100644 --- a/modules/javafx.base/src/main/java/javafx/event/Event.java +++ b/modules/javafx.base/src/main/java/javafx/event/Event.java @@ -29,6 +29,7 @@ import java.util.EventObject; import javafx.beans.NamedArg; import javafx.beans.property.SimpleBooleanProperty; +import com.sun.javafx.event.EventHelper; import com.sun.javafx.event.EventUtil; // PENDING_DOC_REVIEW @@ -54,6 +55,8 @@ public class Event extends EventObject implements Cloneable { */ public static final EventType ANY = EventType.ROOT; + static { initHelper(); } + /** * Type of the event. */ @@ -129,21 +132,17 @@ public EventType getEventType() { */ public Event copyFor(final Object newSource, final EventTarget newTarget) { final Event newEvent = (Event) clone(); - newEvent.source = (newSource != null) ? newSource : NULL_SOURCE_TARGET; newEvent.target = (newTarget != null) ? newTarget : NULL_SOURCE_TARGET; - // cloning does not clone properties - newEvent.consumed = null; + newEvent.consumed = null; // discard the property which is simply copied newEvent.consumedProperty().bindBidirectional(consumedProperty()); return newEvent; } - // TODO hide behind the accessor - public Event copyForTest(final Object newSource, final EventTarget newTarget) { - final Event newEvent = (Event) clone(); + private Event copyForTest(final Object newSource, final EventTarget newTarget) { + final Event newEvent = (Event) clone(); newEvent.source = (newSource != null) ? newSource : NULL_SOURCE_TARGET; newEvent.target = (newTarget != null) ? newTarget : NULL_SOURCE_TARGET; - // cloning does not clone properties newEvent.consumed = null; return newEvent; } @@ -216,4 +215,13 @@ public static void fireEvent(EventTarget eventTarget, Event event) { EventUtil.fireEvent(eventTarget, event); } + + private static void initHelper() { + EventHelper.setAccessor(new EventHelper.Accessor() { + @Override + public Event copyForTest(Event ev, Object newSource, EventTarget newTarget) { + return ev.copyForTest(newSource, newTarget); + } + }); + } } From d66cd4abee3faa6d4d5a38c9fffb6fd13abdc666 Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Wed, 31 Jul 2024 17:43:41 -0700 Subject: [PATCH 04/10] simpler --- .../com/sun/javafx/event/EventHelper.java | 63 ------------------- .../java/com/sun/javafx/event/EventUtil.java | 2 +- .../src/main/java/javafx/event/Event.java | 31 +++------ 3 files changed, 8 insertions(+), 88 deletions(-) delete mode 100644 modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java diff --git a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java deleted file mode 100644 index 1d335347a77..00000000000 --- a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.javafx.event; - -import javafx.event.Event; -import javafx.event.EventTarget; - -/** - * Provides access to private methods in Event. - */ -public class EventHelper { - static { - // copied from com.sun.javafx.util.Utils in javafx.graphics; - try { - Class c = Event.class; - Class.forName(c.getName(), true, c.getClassLoader()); - } catch (ClassNotFoundException e) { - throw new AssertionError(e); // Can't happen - } - } - - public interface Accessor { - public Event copyForTest(Event ev, Object newSource, EventTarget newTarget); - } - - private static Accessor accessor; - - private EventHelper() { - } - - public static void setAccessor(Accessor a) { - if (accessor != null) { - throw new IllegalStateException(); - } - accessor = a; - } - - public static Event copyForTest(Event ev, Object newSource, EventTarget newTarget) { - return accessor.copyForTest(ev, newSource, newTarget); - } -} diff --git a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java index b98895a5fc2..6c3a8a17635 100644 --- a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java +++ b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java @@ -40,7 +40,7 @@ public final class EventUtil { public static Event fireEvent(EventTarget eventTarget, Event event) { if (event.getTarget() != eventTarget) { - event = EventHelper.copyForTest(event, event.getSource(), eventTarget); + event = event.copyFor(event.getSource(), eventTarget); } if (eventDispatchChainInUse.getAndSet(true)) { diff --git a/modules/javafx.base/src/main/java/javafx/event/Event.java b/modules/javafx.base/src/main/java/javafx/event/Event.java index 9423c2482ee..cd0b0ba9d16 100644 --- a/modules/javafx.base/src/main/java/javafx/event/Event.java +++ b/modules/javafx.base/src/main/java/javafx/event/Event.java @@ -25,12 +25,12 @@ package javafx.event; -import java.io.IOException; import java.util.EventObject; + +import com.sun.javafx.event.EventUtil; +import java.io.IOException; import javafx.beans.NamedArg; import javafx.beans.property.SimpleBooleanProperty; -import com.sun.javafx.event.EventHelper; -import com.sun.javafx.event.EventUtil; // PENDING_DOC_REVIEW /** @@ -55,8 +55,6 @@ public class Event extends EventObject implements Cloneable { */ public static final EventType ANY = EventType.ROOT; - static { initHelper(); } - /** * Type of the event. */ @@ -71,7 +69,7 @@ public class Event extends EventObject implements Cloneable { /** * Whether this event has been consumed by any filter or handler. */ - private SimpleBooleanProperty consumed; + private transient SimpleBooleanProperty consumed; /** * Construct a new {@code Event} with the specified event type. The source @@ -132,18 +130,12 @@ public EventType getEventType() { */ public Event copyFor(final Object newSource, final EventTarget newTarget) { final Event newEvent = (Event) clone(); - newEvent.source = (newSource != null) ? newSource : NULL_SOURCE_TARGET; - newEvent.target = (newTarget != null) ? newTarget : NULL_SOURCE_TARGET; - newEvent.consumed = null; // discard the property which is simply copied - newEvent.consumedProperty().bindBidirectional(consumedProperty()); - return newEvent; - } - private Event copyForTest(final Object newSource, final EventTarget newTarget) { - final Event newEvent = (Event) clone(); newEvent.source = (newSource != null) ? newSource : NULL_SOURCE_TARGET; newEvent.target = (newTarget != null) ? newTarget : NULL_SOURCE_TARGET; newEvent.consumed = null; + newEvent.consumedProperty().bindBidirectional(consumedProperty()); + return newEvent; } @@ -166,7 +158,7 @@ public final void consume() { } private final SimpleBooleanProperty consumedProperty() { - if (consumed == null) { + if(consumed == null) { consumed = new SimpleBooleanProperty(); } return consumed; @@ -215,13 +207,4 @@ public static void fireEvent(EventTarget eventTarget, Event event) { EventUtil.fireEvent(eventTarget, event); } - - private static void initHelper() { - EventHelper.setAccessor(new EventHelper.Accessor() { - @Override - public Event copyForTest(Event ev, Object newSource, EventTarget newTarget) { - return ev.copyForTest(newSource, newTarget); - } - }); - } } From 38ab8df0402a57645d863fc853374fab84aaa8ef Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Wed, 31 Jul 2024 17:44:45 -0700 Subject: [PATCH 05/10] cleanup --- .../src/main/java/com/sun/javafx/event/EventUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java index 6c3a8a17635..10f9fa05a2b 100644 --- a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java +++ b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From 5777c21731c84274bcf33f636d19e427a7a2d786 Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Fri, 2 Aug 2024 14:43:13 -0700 Subject: [PATCH 06/10] propagate --- .../com/sun/javafx/event/EventHelper.java | 69 +++++++++++++++++++ .../src/main/java/javafx/event/Event.java | 23 +++++-- .../scene/control/skin/SpinnerSkin.java | 14 ++-- 3 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java diff --git a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java new file mode 100644 index 00000000000..2d1d515fc69 --- /dev/null +++ b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.javafx.event; + +import javafx.event.Event; +import javafx.event.EventTarget; + +/** + * Provides access to private methods in Event. + */ +public class EventHelper { + static { + // copied from com.sun.javafx.util.Utils in javafx.graphics; + try { + Class c = Event.class; + Class.forName(c.getName(), true, c.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); // Can't happen + } + } + + public interface Accessor { + public void propagateConsume(Event ev); + } + + private static Accessor accessor; + + private EventHelper() { + } + + public static void setAccessor(Accessor a) { + if (accessor != null) { + throw new IllegalStateException(); + } + accessor = a; + } + + /** + * Causes the {@link Event#consume()} of cloned events to invoke the same + * method in the original event, and vice versa. + * + * @param ev the event + */ + public static void propagateConsume(Event ev) { + accessor.propagateConsume(ev); + } +} diff --git a/modules/javafx.base/src/main/java/javafx/event/Event.java b/modules/javafx.base/src/main/java/javafx/event/Event.java index cd0b0ba9d16..3f97038435f 100644 --- a/modules/javafx.base/src/main/java/javafx/event/Event.java +++ b/modules/javafx.base/src/main/java/javafx/event/Event.java @@ -25,12 +25,12 @@ package javafx.event; -import java.util.EventObject; - -import com.sun.javafx.event.EventUtil; import java.io.IOException; +import java.util.EventObject; import javafx.beans.NamedArg; import javafx.beans.property.SimpleBooleanProperty; +import com.sun.javafx.event.EventHelper; +import com.sun.javafx.event.EventUtil; // PENDING_DOC_REVIEW /** @@ -55,6 +55,8 @@ public class Event extends EventObject implements Cloneable { */ public static final EventType ANY = EventType.ROOT; + static { initHelper(); } + /** * Type of the event. */ @@ -70,6 +72,7 @@ public class Event extends EventObject implements Cloneable { * Whether this event has been consumed by any filter or handler. */ private transient SimpleBooleanProperty consumed; + private transient boolean propagateConsume; /** * Construct a new {@code Event} with the specified event type. The source @@ -134,7 +137,10 @@ public Event copyFor(final Object newSource, final EventTarget newTarget) { newEvent.source = (newSource != null) ? newSource : NULL_SOURCE_TARGET; newEvent.target = (newTarget != null) ? newTarget : NULL_SOURCE_TARGET; newEvent.consumed = null; - newEvent.consumedProperty().bindBidirectional(consumedProperty()); + + if (propagateConsume) { + newEvent.consumedProperty().bindBidirectional(consumedProperty()); + } return newEvent; } @@ -207,4 +213,13 @@ public static void fireEvent(EventTarget eventTarget, Event event) { EventUtil.fireEvent(eventTarget, event); } + + private static void initHelper() { + EventHelper.setAccessor(new EventHelper.Accessor() { + @Override + public void propagateConsume(Event ev) { + ev.propagateConsume = true; + } + }); + } } diff --git a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/SpinnerSkin.java b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/SpinnerSkin.java index 3cff164b9ac..d8d86740d30 100644 --- a/modules/javafx.controls/src/main/java/javafx/scene/control/skin/SpinnerSkin.java +++ b/modules/javafx.controls/src/main/java/javafx/scene/control/skin/SpinnerSkin.java @@ -40,7 +40,7 @@ import javafx.scene.input.KeyEvent; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; - +import com.sun.javafx.event.EventHelper; import com.sun.javafx.scene.ParentHelper; import com.sun.javafx.scene.control.FakeFocusTextField; import com.sun.javafx.scene.control.ListenerHelper; @@ -194,9 +194,15 @@ public void executeAccessibleAction(AccessibleAction action, Object... parameter // Fix for the regression noted in a comment in RT-29885. // This forwards the event down into the TextField when // the key event is actually received by the Spinner. - textField.fireEvent(ke.copyFor(textField, textField)); - - if (ke.getCode() == KeyCode.ENTER) return; + KeyEvent ev = ke.copyFor(textField, textField); + EventHelper.propagateConsume(ev); + textField.fireEvent(ev); + + if (ke.getCode() == KeyCode.ENTER) { + if (!ev.isConsumed()) { + return; + } + } ke.consume(); } From 0a30d4c9971c9b14d57d15dd38f02f1685a33fa8 Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Fri, 2 Aug 2024 15:22:15 -0700 Subject: [PATCH 07/10] only when consumed --- .../sun/javafx/scene/control/behavior/TextFieldBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java index b19542dcbcd..b2003f9ddec 100644 --- a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java +++ b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java @@ -164,7 +164,7 @@ public void setTextFieldSkin(TextFieldSkin skin) { textField.fireEvent(actionEvent); // fix of JDK-8207759: reverted logic // mapping not auto-consume and consume if handled by action - if (onAction != null || actionEvent.isConsumed()) { + if (onAction != null && actionEvent.isConsumed()) { event.consume(); } } From 551ed976c69292d68a2878b5b37901086f46cb11 Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Fri, 2 Aug 2024 15:43:18 -0700 Subject: [PATCH 08/10] only if consumed --- .../sun/javafx/scene/control/behavior/TextFieldBehavior.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java index b2003f9ddec..9669fe4863e 100644 --- a/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java +++ b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java @@ -156,7 +156,6 @@ public void setTextFieldSkin(TextFieldSkin skin) { @Override protected void fire(KeyEvent event) { TextField textField = getNode(); - EventHandler onAction = textField.getOnAction(); // use textField as target to prevent immediate copy in dispatch ActionEvent actionEvent = new ActionEvent(textField, textField); @@ -164,7 +163,7 @@ public void setTextFieldSkin(TextFieldSkin skin) { textField.fireEvent(actionEvent); // fix of JDK-8207759: reverted logic // mapping not auto-consume and consume if handled by action - if (onAction != null && actionEvent.isConsumed()) { + if (actionEvent.isConsumed()) { event.consume(); } } From 48022d6bc58939d1c14bab5a7ed827fbaaf755e6 Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Tue, 13 Aug 2024 14:32:37 -0700 Subject: [PATCH 09/10] avoid csr --- modules/javafx.base/src/main/java/javafx/event/Event.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/javafx.base/src/main/java/javafx/event/Event.java b/modules/javafx.base/src/main/java/javafx/event/Event.java index 3f97038435f..bddca5cbc28 100644 --- a/modules/javafx.base/src/main/java/javafx/event/Event.java +++ b/modules/javafx.base/src/main/java/javafx/event/Event.java @@ -152,14 +152,14 @@ public Event copyFor(final Object newSource, final EventTarget newTarget) { * @return {@code true} if this {@code Event} has been consumed, * {@code false} otherwise */ - public final boolean isConsumed() { + public boolean isConsumed() { return consumed == null ? false : consumed.get(); } /** * Marks this {@code Event} as consumed. This stops its further propagation. */ - public final void consume() { + public void consume() { consumedProperty().set(true); } From fcc0b4d1718e39be8e2c9404a5ef93e0bc51772d Mon Sep 17 00:00:00 2001 From: Andy Goryachev Date: Wed, 2 Oct 2024 15:37:23 -0700 Subject: [PATCH 10/10] no csr --- .../com/sun/javafx/event/EventHelper.java | 3 +- .../src/main/java/javafx/event/Event.java | 34 +++++++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java index 2d1d515fc69..534d492d9d5 100644 --- a/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java +++ b/modules/javafx.base/src/main/java/com/sun/javafx/event/EventHelper.java @@ -58,8 +58,7 @@ public static void setAccessor(Accessor a) { } /** - * Causes the {@link Event#consume()} of cloned events to invoke the same - * method in the original event, and vice versa. + * Causes the {@link Event#consume()} of cloned events to consume the original event. * * @param ev the event */ diff --git a/modules/javafx.base/src/main/java/javafx/event/Event.java b/modules/javafx.base/src/main/java/javafx/event/Event.java index bddca5cbc28..c82de2279bd 100644 --- a/modules/javafx.base/src/main/java/javafx/event/Event.java +++ b/modules/javafx.base/src/main/java/javafx/event/Event.java @@ -26,9 +26,10 @@ package javafx.event; import java.io.IOException; +import java.util.ArrayList; import java.util.EventObject; +import java.util.List; import javafx.beans.NamedArg; -import javafx.beans.property.SimpleBooleanProperty; import com.sun.javafx.event.EventHelper; import com.sun.javafx.event.EventUtil; @@ -71,8 +72,10 @@ public class Event extends EventObject implements Cloneable { /** * Whether this event has been consumed by any filter or handler. */ - private transient SimpleBooleanProperty consumed; + protected boolean consumed; + private transient boolean propagateConsume; + private transient List consumeListeners; /** * Construct a new {@code Event} with the specified event type. The source @@ -136,10 +139,10 @@ public Event copyFor(final Object newSource, final EventTarget newTarget) { newEvent.source = (newSource != null) ? newSource : NULL_SOURCE_TARGET; newEvent.target = (newTarget != null) ? newTarget : NULL_SOURCE_TARGET; - newEvent.consumed = null; + newEvent.consumed = false; if (propagateConsume) { - newEvent.consumedProperty().bindBidirectional(consumedProperty()); + newEvent.setNotifyConsumed(this); } return newEvent; @@ -153,21 +156,32 @@ public Event copyFor(final Object newSource, final EventTarget newTarget) { * {@code false} otherwise */ public boolean isConsumed() { - return consumed == null ? false : consumed.get(); + return consumed; } /** * Marks this {@code Event} as consumed. This stops its further propagation. */ public void consume() { - consumedProperty().set(true); + consumed = true; + + // consume parent events when the child is consumed + if (consumeListeners != null) { + List cs = consumeListeners; + consumeListeners = null; + + for (int i = cs.size() - 1; i >= 0; i--) { + Event ev = cs.get(i); + ev.consume(); + } + } } - private final SimpleBooleanProperty consumedProperty() { - if(consumed == null) { - consumed = new SimpleBooleanProperty(); + private void setNotifyConsumed(Event ev) { + if (consumeListeners == null) { + consumeListeners = new ArrayList(1); } - return consumed; + consumeListeners.add(ev); } /**