diff options
8 files changed, 185 insertions, 145 deletions
diff --git a/WebContent/VAADIN/themes/base/common/common.css b/WebContent/VAADIN/themes/base/common/common.css index ccdd5190fc..b3bf6084be 100644 --- a/WebContent/VAADIN/themes/base/common/common.css +++ b/WebContent/VAADIN/themes/base/common/common.css @@ -247,5 +247,4 @@ div.v-app-loading { .v-scrollable { overflow: auto; - -webkit-overflow-scrolling: touch; } diff --git a/src/com/vaadin/terminal/ClassResource.java b/src/com/vaadin/terminal/ClassResource.java index fa196e90d9..e7419576f1 100644 --- a/src/com/vaadin/terminal/ClassResource.java +++ b/src/com/vaadin/terminal/ClassResource.java @@ -60,13 +60,7 @@ public class ClassResource implements ApplicationResource, Serializable { * the application this resource will be added to. */ public ClassResource(String resourceName, Application application) { - associatedClass = application.getClass(); - this.resourceName = resourceName; - this.application = application; - if (resourceName == null) { - throw new NullPointerException(); - } - application.addResource(this); + this(application.getClass(), resourceName, application); } /** diff --git a/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java index 444909c1b1..d9320787e8 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java +++ b/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java @@ -353,8 +353,6 @@ public class VAccordion extends VTabsheetBase { touchScrollHandler.addElement(getContainerElement()); - sinkEvents(Event.MOUSEEVENTS); - close(); } diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java index e5e7dbba8b..584be55bce 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java +++ b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java @@ -10,6 +10,7 @@ import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.Accessibility; @@ -61,7 +62,9 @@ public class VButton extends FocusWidget implements ClickHandler { private boolean isCapturing; /** - * If <code>true</code>, this widget has focus with the space bar down. + * If <code>true</code>, this widget has focus with the space bar down. This + * means that we will get events when the button is released, but we should + * trigger the button only if the button is still focused at that point. */ private boolean isFocusing; @@ -74,6 +77,14 @@ public class VButton extends FocusWidget implements ClickHandler { protected int clickShortcut = 0; + private HandlerRegistration focusHandlerRegistration; + private HandlerRegistration blurHandlerRegistration; + + /** + * If caption should be rendered in HTML + */ + protected boolean htmlCaption = false; + public VButton() { super(DOM.createDiv()); setTabIndex(0); @@ -229,37 +240,28 @@ public class VButton extends FocusWidget implements ClickHandler { if ((event.getTypeInt() & Event.KEYEVENTS) != 0) { switch (type) { case Event.ONKEYDOWN: + // Stop propagation when the user starts pressing a button that + // we are handling to prevent actions from getting triggered if (event.getKeyCode() == 32 /* space */) { isFocusing = true; event.preventDefault(); + event.stopPropagation(); + } else if (event.getKeyCode() == KeyCodes.KEY_ENTER) { + event.stopPropagation(); } break; case Event.ONKEYUP: if (isFocusing && event.getKeyCode() == 32 /* space */) { isFocusing = false; - - /* - * If click shortcut is space then the shortcut handler will - * take care of the click. - */ - if (clickShortcut != 32 /* space */) { - onClick(); - } - + onClick(); + event.stopPropagation(); event.preventDefault(); } break; case Event.ONKEYPRESS: if (event.getKeyCode() == KeyCodes.KEY_ENTER) { - - /* - * If click shortcut is enter then the shortcut handler will - * take care of the click. - */ - if (clickShortcut != KeyCodes.KEY_ENTER) { - onClick(); - } - + onClick(); + event.stopPropagation(); event.preventDefault(); } break; @@ -284,6 +286,7 @@ public class VButton extends FocusWidget implements ClickHandler { * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event * .dom.client.ClickEvent) */ + @Override public void onClick(ClickEvent event) { if (BrowserInfo.get().isSafari()) { VButton.this.setFocus(true); diff --git a/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java index bdd1204fa6..4565c28fa5 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java @@ -4396,7 +4396,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private String[] actionKeys = null; private final TableRowElement rowElement; - private boolean mDown; private int index; private Event touchStart; private static final String ROW_CLASSNAME_EVEN = CLASSNAME + "-row"; @@ -4407,6 +4406,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private Timer dragTouchTimeout; private int touchStartY; private int touchStartX; + private boolean isDragging = false; private VScrollTableRow(int rowKey) { this.rowKey = rowKey; @@ -4795,40 +4795,24 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } } - private boolean wasSignificantMove = false; - private boolean isDragging = false; - /** - * Special handler for touch devices + * Special handler for touch devices that support native scrolling * - * @param event + * @return Whether the event was handled by this method. */ - public void onTouchBrowserEvent(final Event event) { - VConsole.log("-- START ONTOUCHBROWSEREVENT"); - if (enabled) { + private boolean handleTouchEvent(final Event event) { + + boolean touchEventHandled = false; + + if (enabled && hasNativeTouchScrolling) { final Element targetTdOrTr = getEventTargetTdOrTr(event); final int type = event.getTypeInt(); switch (type) { - case Event.ONCONTEXTMENU: - showContextMenu(event); - if (enabled - && (actionKeys != null || client - .hasEventListeners(VScrollTable.this, - ITEM_CLICK_EVENT_ID))) { - /* - * Prevent browser context menu only if there are - * action handlers or item click listeners - * registered - */ - event.stopPropagation(); - event.preventDefault(); - } - break; case Event.ONTOUCHSTART: + touchEventHandled = true; touchStart = event; isDragging = false; - wasSignificantMove = false; Touch touch = event.getChangedTouches().get(0); // save position to fields, touches in events are same // instance during the operation. @@ -4841,14 +4825,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets, @Override public void run() { if (touchStart != null) { - VConsole.log("DRAGGING"); + // Start a drag if a finger is held + // in place long enough, then moved isDragging = true; } } }; - VConsole.log("START DRAG TIMEOUT"); - dragTouchTimeout.schedule(TOUCHSCROLL_TIMEOUT); } + dragTouchTimeout.schedule(TOUCHSCROLL_TIMEOUT); } if (actionKeys != null) { @@ -4857,123 +4841,68 @@ public class VScrollTable extends FlowPanel implements HasWidgets, @Override public void run() { if (touchStart != null) { - VConsole.log("SHOW CONTEXT"); + // Open the context menu if finger + // is held in place long enough. showContextMenu(touchStart); event.preventDefault(); touchStart = null; - } } }; - VConsole.log("START CONTEXT TIMEOUT"); - - contextTouchTimeout.cancel(); - contextTouchTimeout - .schedule(TOUCH_CONTEXT_MENU_TIMEOUT); } + contextTouchTimeout + .schedule(TOUCH_CONTEXT_MENU_TIMEOUT); } break; case Event.ONTOUCHMOVE: + touchEventHandled = true; if (isSignificantMove(event)) { - wasSignificantMove = true; if (contextTouchTimeout != null) { + // Moved finger before the context menu timer + // expired, so let the browser handle this as a + // scroll. contextTouchTimeout.cancel(); + contextTouchTimeout = null; } if (!isDragging && dragTouchTimeout != null) { - VConsole.log("CANCEL DRAG TIMEOUT"); + // Moved finger before the drag timer expired, + // so let the browser handle this as a scroll. dragTouchTimeout.cancel(); dragTouchTimeout = null; } - if (isDragging) { - if (dragmode != 0 && touchStart != null) { - event.preventDefault(); - event.stopPropagation(); - VConsole.log("START DRAG"); - startRowDrag(touchStart, type, targetTdOrTr); - } - isDragging = false; + + if (dragmode != 0 && touchStart != null + && isDragging) { + event.preventDefault(); + event.stopPropagation(); + startRowDrag(touchStart, type, targetTdOrTr); } touchStart = null; } break; case Event.ONTOUCHEND: case Event.ONTOUCHCANCEL: - VConsole.log("ONTOUCHEND"); + touchEventHandled = true; if (contextTouchTimeout != null) { - VConsole.log("CANCEL CONTEXT TIMEOUT"); contextTouchTimeout.cancel(); } if (dragTouchTimeout != null) { - VConsole.log("CANCEL DRAG TIMEOUT"); dragTouchTimeout.cancel(); } if (touchStart != null) { event.preventDefault(); event.stopPropagation(); + if (!BrowserInfo.get().isAndroid()) { + Util.simulateClickFromTouchEvent(touchStart, + this); + } touchStart = null; } isDragging = false; - VConsole.log("END ONTOUCHEND"); break; - case Event.ONMOUSEDOWN: - VConsole.log("ONMOUSEDOWN"); - if (targetTdOrTr != null) { - setRowFocus(this); - ensureFocus(); - if (dragmode != 0 - && (event.getButton() == NativeEvent.BUTTON_LEFT)) { - startRowDrag(event, event.getTypeInt(), - targetTdOrTr); - } else { - event.stopPropagation(); - } - - event.preventDefault(); - } - break; - case Event.ONMOUSEOUT: - VConsole.log("ONMOUSEOUT"); - break; - case Event.ONMOUSEUP: - VConsole.log("ONMOUSEUP"); - if (targetTdOrTr != null) { - if (isSelectable()) { - boolean currentlyJustThisRowSelected = selectedRowKeys - .size() == 1 - && selectedRowKeys.contains(getKey()); - - if (!currentlyJustThisRowSelected) { - if (isSingleSelectMode() - || isMultiSelectModeDefault()) { - deselectAll(); - } - toggleSelection(); - } else if ((isSingleSelectMode() || isMultiSelectModeSimple()) - && nullSelectionAllowed) { - toggleSelection(); - } - - selectionRangeStart = this; - setRowFocus(this); - - event.preventDefault(); - event.stopPropagation(); - } - } - - break; - case Event.ONDBLCLICK: - if (targetTdOrTr != null) { - handleClickEvent(event, targetTdOrTr, true); - } - break; - default: } } - VConsole.log("-- SUPER ONBROWSEREVENT"); - - super.onBrowserEvent(event); - VConsole.log("-- END ONTOUCHBROWSEREVENT"); + return touchEventHandled; } /* @@ -4982,12 +4911,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets, @Override public void onBrowserEvent(final Event event) { - if (hasNativeTouchScrolling) { - onTouchBrowserEvent(event); - return; - } + final boolean touchEventHandled = handleTouchEvent(event); - if (enabled) { + if (enabled && !touchEventHandled) { final int type = event.getTypeInt(); final Element targetTdOrTr = getEventTargetTdOrTr(event); if (type == Event.ONCONTEXTMENU) { @@ -5020,7 +4946,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, break; case Event.ONMOUSEUP: if (targetCellOrRowFound) { - mDown = false; /* * Queue here, send at the same time as the * corresponding value change event - see #7127 @@ -5263,9 +5188,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } break; case Event.ONMOUSEOUT: - if (targetCellOrRowFound) { - mDown = false; - } break; default: break; @@ -5295,7 +5217,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets, protected void startRowDrag(Event event, final int type, Element targetTdOrTr) { - mDown = true; VTransferable transferable = new VTransferable(); transferable.setDragSource(ConnectorMap.get(client) .getConnector(VScrollTable.this)); diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java index 876fe593e2..9551cbaaab 100644 --- a/src/com/vaadin/ui/Button.java +++ b/src/com/vaadin/ui/Button.java @@ -38,10 +38,12 @@ public class Button extends AbstractComponent implements Action.ShortcutNotifier { private ButtonServerRpc rpc = new ButtonServerRpc() { + @Override public void click(MouseEventDetails mouseEventDetails) { fireClick(mouseEventDetails); } + @Override public void disableOnClick() { // Could be optimized so the button is not repainted because of // this (client side has already disabled the button) @@ -330,20 +332,24 @@ public class Button extends AbstractComponent implements fireEvent(new Button.ClickEvent(this, details)); } + @Override public void addListener(BlurListener listener) { addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, BlurListener.blurMethod); } + @Override public void removeListener(BlurListener listener) { removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); } + @Override public void addListener(FocusListener listener) { addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, FocusListener.focusMethod); } + @Override public void removeListener(FocusListener listener) { removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); @@ -469,10 +475,12 @@ public class Button extends AbstractComponent implements requestRepaint(); } + @Override public int getTabIndex() { return tabIndex; } + @Override public void setTabIndex(int tabIndex) { this.tabIndex = tabIndex; diff --git a/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.html b/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.html new file mode 100644 index 0000000000..5ec33f09fa --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.html @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.button.ButtonEnterWithWindowShortcut?restartApplication</td> + <td></td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]</td> + <td>enter</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_0</td> + <td>1. button click listener fired</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::</td> + <td>enter</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_0</td> + <td>2. enter pressed in window</td> +</tr> +<!-- Can't test using space because of #8827 --> +<!-- <tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]</td> + <td>space</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_0</td> + <td>3. button click listener fired</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::</td> + <td>space</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_0</td> + <td>4. space pressed in window</td> +</tr> --> +</tbody></table> +</body> +</html> diff --git a/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.java b/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.java new file mode 100644 index 0000000000..7efd40ca5d --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.java @@ -0,0 +1,55 @@ +package com.vaadin.tests.components.button; + +import com.vaadin.event.Action; +import com.vaadin.event.Action.Handler; +import com.vaadin.event.ShortcutAction; +import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.util.Log; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; + +public class ButtonEnterWithWindowShortcut extends TestBase { + Log log = new Log(5); + + @Override + protected void setup() { + getMainWindow().addActionHandler(new Handler() { + private static final long serialVersionUID = -4976129418325394913L; + + public void handleAction(Action action, Object sender, Object target) { + log.log(action.getCaption() + " pressed in window"); + } + + public Action[] getActions(Object target, Object sender) { + ShortcutAction enter = new ShortcutAction("enter", + ShortcutAction.KeyCode.ENTER, null); + ShortcutAction space = new ShortcutAction("space", + ShortcutAction.KeyCode.SPACEBAR, null); + return new Action[] { enter, space }; + } + }); + + Button button = new Button("Focus me and press enter", + new ClickListener() { + public void buttonClick(ClickEvent event) { + log.log("button click listener fired"); + } + }); + button.focus(); + + addComponent(log); + addComponent(button); + } + + @Override + protected String getDescription() { + return "Pressing enter or space with the button focused should trigger the button click listener and not the shortcut action on the window."; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(5433); + } + +} |