Fixing issue 3186 by modifying ListenerWrapper to provide correct values for x and y and adding a visual test case for this problem.
Review by:jlabanca
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4299 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3186.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3186.java
new file mode 100644
index 0000000..a8360ca
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue3186.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.AbsolutePanel;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.FocusPanel;
+import com.google.gwt.user.client.ui.MouseListener;
+import com.google.gwt.user.client.ui.MouseListenerCollection;
+import com.google.gwt.user.client.ui.Widget;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Ensure the ListenerWrapper for mouse still works like the old listeners did.
+ */
+@SuppressWarnings("deprecation")
+public class Issue3186 extends AbstractIssue {
+
+ enum VisibleEvents {
+ mouseDown, mouseEnter, mouseLeave, mouseMove, mouseUp
+ }
+
+ private final class TestWidget extends FocusPanel {
+ private class Control implements MouseListener {
+ int controlX;
+ int controlY;
+ int controlMouseEnter;
+ int controlMouseLeave;
+
+ public void onMouseDown(Widget sender, int x, int y) {
+ this.controlX = x;
+ this.controlY = y;
+ }
+
+ public void onMouseEnter(Widget sender) {
+ ++controlMouseEnter;
+ }
+
+ public void onMouseLeave(Widget sender) {
+ ++controlMouseLeave;
+ }
+
+ public void onMouseMove(Widget sender, int x, int y) {
+ this.controlX = x;
+ this.controlY = y;
+ }
+
+ public void onMouseUp(Widget sender, int x, int y) {
+ this.controlX = x;
+ this.controlY = y;
+ }
+ }
+
+ private class Current implements MouseListener {
+ private int mouseEnterCount;
+ private int mouseLeaveCount;
+
+ public void onMouseDown(Widget sender, int x, int y) {
+ check(x, y, VisibleEvents.mouseDown);
+ }
+
+ public void onMouseEnter(Widget sender) {
+ ++mouseEnterCount;
+ if (mouseEnterCount != control.controlMouseEnter) {
+ fail("recieved:" + mouseEnterCount + " events, expected:"
+ + control.controlMouseEnter, VisibleEvents.mouseEnter);
+ } else {
+ pass(VisibleEvents.mouseEnter);
+ }
+ sender.getElement().getStyle().setProperty("background", "yellow");
+ }
+
+ public void onMouseLeave(Widget sender) {
+ ++mouseLeaveCount;
+ if (mouseLeaveCount != control.controlMouseLeave) {
+ fail("recieved:" + mouseLeaveCount + " events, expected:"
+ + control.controlMouseLeave, VisibleEvents.mouseLeave);
+ } else {
+ pass(VisibleEvents.mouseLeave);
+ }
+
+ sender.getElement().getStyle().setProperty("background", "");
+ }
+
+ public void onMouseMove(Widget sender, int x, int y) {
+ check(x, y, VisibleEvents.mouseMove);
+ }
+
+ public void onMouseUp(Widget sender, int x, int y) {
+ check(x, y, VisibleEvents.mouseUp);
+ }
+
+ private void check(int x, int y, VisibleEvents event) {
+ String errorReport = getErrorReport(x, y);
+ if (errorReport == null) {
+ eventToElement.get(event).setInnerHTML(
+ "<span style='color:green'>pass</span>");
+ } else {
+ fail(errorReport, event);
+ }
+ }
+
+ private String getErrorReport(int x, int y) {
+ String errorReport = null;
+ if (x != control.controlX) {
+ errorReport = "wanted x: " + control.controlX + " actual x" + x;
+ } else if (y != control.controlY) {
+ errorReport += "wanted y: " + control.controlY + " actual y" + y;
+ }
+ return errorReport;
+ }
+ }
+
+ private FlexTable layout = null;
+ private MouseListenerCollection collection = new MouseListenerCollection();
+
+ private Control control = new Control();
+ private Current current = new Current();
+ private final Map<VisibleEvents, Element> eventToElement = new HashMap<VisibleEvents, Element>();
+
+ public TestWidget() {
+ layout = new FlexTable();
+ layout.setCellPadding(3);
+ layout.setBorderWidth(2);
+
+ layout.setHTML(0, 0, "<b>MouseEvents</b>");
+ layout.setHTML(0, 1, "<b>Status</b>");
+
+ for (VisibleEvents e : VisibleEvents.values()) {
+ eventToElement.put(e, addResultRow(e.name()));
+ }
+ add(layout);
+ this.addMouseListener(current);
+ collection.add(control);
+ }
+
+ public void fail(String errorReport, VisibleEvents event) {
+ eventToElement.get(event).setInnerHTML(
+ "<span style='color:red'>" + errorReport + "</span>");
+ }
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ collection.fireMouseEvent(this, event);
+ super.onBrowserEvent(event);
+ }
+
+ public void pass(VisibleEvents event) {
+ eventToElement.get(event).setInnerHTML(
+ "<span style='color:green'>pass</span>");
+ }
+
+ private Element addResultRow(String eventName) {
+ int row = layout.getRowCount();
+ layout.setHTML(row, 0, eventName);
+ layout.setHTML(row, 1, "<span style='color:red'>?</span>");
+ Element cell = layout.getCellFormatter().getElement(row, 1);
+ return cell;
+ }
+ }
+
+ @Override
+ public Widget createIssue() {
+ AbsolutePanel p = new AbsolutePanel();
+ p.setHeight("500px");
+ p.setWidth("500px");
+ final TestWidget dialog = showTestWidget();
+ p.add(dialog, 100, 100);
+ return p;
+ }
+
+ @Override
+ public String getInstructions() {
+ return "move your mouse around ";
+ }
+
+ @Override
+ public String getSummary() {
+ return "mouse listeners work the same";
+ }
+
+ @Override
+ public boolean hasCSS() {
+ return false;
+ }
+
+ private TestWidget showTestWidget() {
+ final TestWidget dialog = new TestWidget();
+ return dialog;
+ }
+
+}
diff --git a/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java b/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java
index 1ea7741..ad0dbb7 100644
--- a/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java
+++ b/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java
@@ -271,25 +271,44 @@
}
public void onMouseDown(MouseDownEvent event) {
- listener.onMouseDown(source(event), event.getClientX(),
- event.getClientY());
+ Widget source = source(event);
+ Element elem = source.getElement();
+ listener.onMouseDown(source, event.getRelativeX(elem),
+ event.getRelativeY(elem));
}
public void onMouseMove(MouseMoveEvent event) {
- listener.onMouseMove(source(event), event.getClientX(),
- event.getClientY());
+ Widget source = source(event);
+ Element elem = source.getElement();
+ listener.onMouseMove(source, event.getRelativeX(elem),
+ event.getRelativeY(elem));
}
public void onMouseOut(MouseOutEvent event) {
- listener.onMouseLeave(source(event));
+ // Only fire the mouseLeave event if it's actually leaving this
+ // widget.
+ Element to = event.getToElement();
+ Widget source = source(event);
+ if (to == null || !source.getElement().isOrHasChild(to)) {
+ listener.onMouseLeave(source(event));
+ }
}
public void onMouseOver(MouseOverEvent event) {
- listener.onMouseEnter(source(event));
+ // Only fire the mouseEnter event if it's coming from outside this
+ // widget.
+ Element from = event.getFromElement();
+ Widget source = source(event);
+ if (from == null || !source.getElement().isOrHasChild(from)) {
+ listener.onMouseEnter(source(event));
+ }
}
public void onMouseUp(MouseUpEvent event) {
- listener.onMouseUp(source(event), event.getClientX(), event.getClientY());
+ Widget source = source(event);
+ Element elem = source.getElement();
+ listener.onMouseUp(source, event.getRelativeX(elem),
+ event.getRelativeY(elem));
}
}
public static class MouseWheel extends ListenerWrapper<MouseWheelListener> implements
@@ -510,6 +529,8 @@
EventListener listener, Type... keys) {
HandlerManager manager = eventSource.getHandlers();
if (manager != null) {
+ // This is a direct copy of the baseRemove from
+ // com.google.gwt.user.client.ListenerWrapper. Change in parallel.
for (Type<H> key : keys) {
int handlerCount = manager.getHandlerCount(key);
// We are removing things as we traverse, have to go backward