diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 9ad2d81c0846..73f7ca0608ed 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -17,7 +17,6 @@ package com.intellij.openapi.editor.impl; import com.intellij.Patches; import com.intellij.application.options.OptionsConstants; -import com.intellij.codeInsight.daemon.GutterMark; import com.intellij.codeInsight.hint.DocumentFragmentTooltipRenderer; import com.intellij.codeInsight.hint.EditorFragmentComponent; import com.intellij.codeInsight.hint.TooltipController; @@ -4143,7 +4142,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (isColumnMode() || e.isAltDown()) { final LogicalPosition blockStart = selectionModel.hasBlockSelection() ? selectionModel.getBlockStart() : oldLogicalCaret; selectionModel.setBlockSelection(blockStart, getCaretModel().getLogicalPosition()); - IdeEventQueue.getInstance().blockNextEvents(e); // don't process action on mouse released (IDEA-53663) } else { if (getMouseSelectionState() != MOUSE_SELECTION_STATE_NONE) { diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java index 42a8d9455c06..b8095397e016 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java @@ -56,6 +56,7 @@ public final class IdeMouseEventDispatcher { private final ArrayList myActions = new ArrayList(1); private final Map myRootPane2BlockedId = new HashMap(); private int myLastHorScrolledComponentHash = 0; + private MouseEvent myPreviousMouseEvent; // Don't compare MouseEvent ids. Swing has wrong sequence of events: first is mouse_clicked(500) // then mouse_pressed(501), mouse_released(502) etc. Here, mouse events sorted so we can compare @@ -125,6 +126,9 @@ public final class IdeMouseEventDispatcher { * to normal event dispatching. */ public boolean dispatchMouseEvent(MouseEvent e) { + MouseEvent previousEvent = myPreviousMouseEvent; + myPreviousMouseEvent = e; + Component c = e.getComponent(); //frame activation by mouse click @@ -160,6 +164,10 @@ public final class IdeMouseEventDispatcher { ignore = true; } + if (e.getID() == MOUSE_RELEASED && previousEvent != null && previousEvent.getID() == MOUSE_DRAGGED) { + ignore = true; // we don't want to process action bindings on mouse release at the end of drag operation + } + final JRootPane root = findRoot(e); if (root != null) { final Integer lastId = myRootPane2BlockedId.get(root); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcherTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcherTest.java new file mode 100644 index 000000000000..1db0bbf14976 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcherTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * 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.intellij.openapi.keymap.impl; + +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.MouseShortcut; +import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.testFramework.LightPlatformTestCase; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; + +public class IdeMouseEventDispatcherTest extends LightPlatformTestCase { + private static final String OUR_TEST_ACTION = "IdeMouseEventDispatcherTestAction"; + + private Component myEventSource; + private int myActionExecutionCount; + + public void setUp() throws Exception { + super.setUp(); + + ActionManager.getInstance().registerAction(OUR_TEST_ACTION, new EmptyAction()); + KeymapManager.getInstance().getActiveKeymap().addShortcut(OUR_TEST_ACTION, new MouseShortcut(MouseEvent.BUTTON2, 0, 1)); + + myEventSource = new JPanel(); + myEventSource.setSize(1,1); + } + + @Override + public void tearDown() throws Exception { + KeymapManager.getInstance().getActiveKeymap().removeShortcut(OUR_TEST_ACTION, new MouseShortcut(MouseEvent.BUTTON2, 0, 1)); + ActionManager.getInstance().unregisterAction(OUR_TEST_ACTION); + super.tearDown(); + } + + public void testActionTriggering() throws Exception { + IdeMouseEventDispatcher dispatcher = new IdeMouseEventDispatcher(); + + assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_PRESSED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2))); + assertTrue(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_RELEASED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2))); + assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_CLICKED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2))); + assertEquals(1, myActionExecutionCount); + } + + public void testActionSuppressionAfterDrag() throws Exception { + IdeMouseEventDispatcher dispatcher = new IdeMouseEventDispatcher(); + + assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_PRESSED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2))); + assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_DRAGGED, 0, 0, 0, 0, 0, false, MouseEvent.BUTTON2))); + assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_RELEASED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2))); + assertEquals(0, myActionExecutionCount); + } + + private class EmptyAction extends AnAction { + private EmptyAction() { + setEnabledInModalContext(true); + } + + @Override + public void actionPerformed(AnActionEvent e){ + myActionExecutionCount++; + } + } + +}