From d941bcfa4a26f6559552bd71417b635adb2fdeb9 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 15 Nov 2017 20:18:15 +0100 Subject: [PATCH 1/3] Activate panes on _any_ click, not just left click --- lib/tab-bar-view.coffee | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/tab-bar-view.coffee b/lib/tab-bar-view.coffee index ae56eae5..4b7f668d 100644 --- a/lib/tab-bar-view.coffee +++ b/lib/tab-bar-view.coffee @@ -422,15 +422,15 @@ class TabBarView @pane.activatePreviousItem() onMouseDown: (event) -> + @pane.activate() unless @pane.isDestroyed() + tab = @tabForElement(event.target) return unless tab - if event.which is 3 or (event.which is 1 and event.ctrlKey is true) - @rightClickedTab?.element.classList.remove('right-clicked') + if event.button is 2 or (event.button is 0 and event.ctrlKey is true) @rightClickedTab = tab - @rightClickedTab.element.classList.add('right-clicked') event.preventDefault() - else if event.which is 2 + else if event.button is 1 # This prevents Chromium from activating "scroll mode" when # middle-clicking while some tabs are off-screen. event.preventDefault() @@ -440,14 +440,13 @@ class TabBarView return unless tab event.preventDefault() - if event.which is 3 or (event.which is 1 and event.ctrlKey is true) + if event.button is 2 or (event.button is 0 and event.ctrlKey is true) # Bail out early when receiving this event, because we have already # handled it in the mousedown handler. return - else if event.which is 1 and not event.target.classList.contains('close-icon') + else if event.button is 0 and not event.target.classList.contains('close-icon') @pane.activateItem(tab.item) - @pane.activate() unless @pane.isDestroyed() - else if event.which is 2 + else if event.button is 1 @pane.destroyItem(tab.item) onDoubleClick: (event) -> From 45244a13a426661b0c66d06b88e95b8d17f72729 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Wed, 15 Nov 2017 20:29:13 +0100 Subject: [PATCH 2/3] Use `button` instead of `which` in specs --- spec/event-helpers.coffee | 53 +++++++++++++++++++++++++++++++++++++++ spec/tabs-spec.coffee | 41 +++++++++++++----------------- 2 files changed, 71 insertions(+), 23 deletions(-) create mode 100644 spec/event-helpers.coffee diff --git a/spec/event-helpers.coffee b/spec/event-helpers.coffee new file mode 100644 index 00000000..7d6b9720 --- /dev/null +++ b/spec/event-helpers.coffee @@ -0,0 +1,53 @@ +buildMouseEvent = (type, target, {button, ctrlKey}={}) -> + event = new MouseEvent(type, {bubbles: true, cancelable: true}) + Object.defineProperty(event, 'button', get: -> button) if button? + Object.defineProperty(event, 'ctrlKey', get: -> ctrlKey) if ctrlKey? + Object.defineProperty(event, 'target', get: -> target) + Object.defineProperty(event, 'srcObject', get: -> target) + spyOn(event, "preventDefault") + event + +module.exports.triggerMouseEvent = (type, target, {which, ctrlKey}={}) -> + event = buildMouseEvent(arguments...) + target.dispatchEvent(event) + event + +module.exports.triggerClickEvent = (target, options) -> + events = { + mousedown: buildMouseEvent('mousedown', target, options), + mouseup: buildMouseEvent('mouseup', target, options), + click: buildMouseEvent('click', target, options) + } + + target.dispatchEvent(events.mousedown) + target.dispatchEvent(events.mouseup) + target.dispatchEvent(events.click) + + events + +module.exports.buildDragEvents = (dragged, dropTarget) -> + dataTransfer = + data: {} + setData: (key, value) -> @data[key] = "#{value}" # Drag events stringify data values + getData: (key) -> @data[key] + + Object.defineProperty( + dataTransfer, + 'items', + get: -> + Object.keys(dataTransfer.data).map((key) -> {type: key}) + ) + + dragStartEvent = buildMouseEvent("dragstart", dragged) + Object.defineProperty(dragStartEvent, 'dataTransfer', get: -> dataTransfer) + + dropEvent = buildMouseEvent("drop", dropTarget) + Object.defineProperty(dropEvent, 'dataTransfer', get: -> dataTransfer) + + [dragStartEvent, dropEvent] + +module.exports.buildWheelEvent = (delta) -> + new WheelEvent("mousewheel", wheelDeltaY: delta) + +module.exports.buildWheelPlusShiftEvent = (delta) -> + new WheelEvent("mousewheel", wheelDeltaY: delta, shiftKey: true) diff --git a/spec/tabs-spec.coffee b/spec/tabs-spec.coffee index 0fbc26f2..59eff769 100644 --- a/spec/tabs-spec.coffee +++ b/spec/tabs-spec.coffee @@ -258,16 +258,15 @@ describe "TabBarView", -> describe "when a tab is clicked", -> it "shows the associated item on the pane and focuses the pane", -> - jasmine.attachToDOM(tabBar.element) # Remove after Atom 1.2.0 is released spyOn(pane, 'activate') - {mousedown, click} = triggerClickEvent(tabBar.tabAtIndex(0).element, which: 1) + {mousedown, click} = triggerClickEvent(tabBar.tabAtIndex(0).element, button: 0) expect(pane.getActiveItem()).toBe(pane.getItems()[0]) # allows dragging expect(mousedown.preventDefault).not.toHaveBeenCalled() expect(click.preventDefault).toHaveBeenCalled() - {mousedown, click} = triggerClickEvent(tabBar.tabAtIndex(2).element, which: 1) + {mousedown, click} = triggerClickEvent(tabBar.tabAtIndex(2).element, button: 0) expect(pane.getActiveItem()).toBe(pane.getItems()[2]) # allows dragging expect(mousedown.preventDefault).not.toHaveBeenCalled() @@ -275,9 +274,7 @@ describe "TabBarView", -> expect(pane.activate.callCount).toBe 2 it "closes the tab when middle clicked", -> - jasmine.attachToDOM(tabBar.element) # Remove after Atom 1.2.0 is released - - {click} = triggerClickEvent(tabBar.tabForItem(editor1).element, which: 2) + {click} = triggerClickEvent(tabBar.tabForItem(editor1).element, button: 1) expect(pane.getItems().length).toBe 2 expect(pane.getItems().indexOf(editor1)).toBe -1 @@ -288,24 +285,22 @@ describe "TabBarView", -> expect(click.preventDefault).toHaveBeenCalled() it "doesn't switch tab when right (or ctrl-left) clicked", -> - jasmine.attachToDOM(tabBar.element) # Remove after Atom 1.2.0 is released - spyOn(pane, 'activate') - {mousedown} = triggerClickEvent(tabBar.tabAtIndex(0).element, which: 3) + {mousedown} = triggerClickEvent(tabBar.tabAtIndex(0).element, button: 2) expect(pane.getActiveItem()).not.toBe pane.getItems()[0] expect(mousedown.preventDefault).toHaveBeenCalled() - {mousedown} = triggerClickEvent(tabBar.tabAtIndex(0).element, which: 1, ctrlKey: true) + {mousedown} = triggerClickEvent(tabBar.tabAtIndex(0).element, button: 0, ctrlKey: true) expect(pane.getActiveItem()).not.toBe pane.getItems()[0] expect(mousedown.preventDefault).toHaveBeenCalled() - expect(pane.activate).not.toHaveBeenCalled() + # We don't switch tabs, but the pane should still be activated + # because of the mouse click + expect(pane.activate).toHaveBeenCalled() describe "when a tab's close icon is clicked", -> it "destroys the tab's item on the pane", -> - jasmine.attachToDOM(tabBar.element) # Remove after Atom 1.2.0 is released - tabBar.tabForItem(editor1).element.querySelector('.close-icon').click() expect(pane.getItems().length).toBe 2 expect(pane.getItems().indexOf(editor1)).toBe -1 @@ -543,7 +538,7 @@ describe "TabBarView", -> describe "when tabs:close-tab is fired", -> it "closes the active tab", -> - triggerClickEvent(tabBar.tabForItem(item2).element, which: 3) + triggerClickEvent(tabBar.tabForItem(item2).element, button: 2) atom.commands.dispatch(tabBar.element, 'tabs:close-tab') expect(pane.getItems().length).toBe 2 expect(pane.getItems().indexOf(item2)).toBe -1 @@ -552,7 +547,7 @@ describe "TabBarView", -> describe "when tabs:close-other-tabs is fired", -> it "closes all other tabs except the active tab", -> - triggerClickEvent(tabBar.tabForItem(item2).element, which: 3) + triggerClickEvent(tabBar.tabForItem(item2).element, button: 2) atom.commands.dispatch(tabBar.element, 'tabs:close-other-tabs') expect(pane.getItems().length).toBe 1 expect(tabBar.getTabs().length).toBe 1 @@ -562,7 +557,7 @@ describe "TabBarView", -> describe "when tabs:close-tabs-to-right is fired", -> it "closes only the tabs to the right of the active tab", -> pane.activateItem(editor1) - triggerClickEvent(tabBar.tabForItem(editor1).element, which: 3) + triggerClickEvent(tabBar.tabForItem(editor1).element, button: 2) atom.commands.dispatch(tabBar.element, 'tabs:close-tabs-to-right') expect(pane.getItems().length).toBe 2 expect(tabBar.getTabs().length).toBe 2 @@ -572,7 +567,7 @@ describe "TabBarView", -> describe "when tabs:close-tabs-to-left is fired", -> it "closes only the tabs to the left of the active tab", -> pane.activateItem(editor1) - triggerClickEvent(tabBar.tabForItem(editor1).element, which: 3) + triggerClickEvent(tabBar.tabForItem(editor1).element, button: 2) atom.commands.dispatch(tabBar.element, 'tabs:close-tabs-to-left') expect(pane.getItems().length).toBe 2 expect(tabBar.getTabs().length).toBe 2 @@ -594,7 +589,7 @@ describe "TabBarView", -> describe "when tabs:split-up is fired", -> it "splits the selected tab up", -> - triggerClickEvent(tabBar.tabForItem(item2).element, which: 3) + triggerClickEvent(tabBar.tabForItem(item2).element, button: 2) expect(atom.workspace.getCenter().getPanes().length).toBe 1 atom.commands.dispatch(tabBar.element, 'tabs:split-up') @@ -604,7 +599,7 @@ describe "TabBarView", -> describe "when tabs:split-down is fired", -> it "splits the selected tab down", -> - triggerClickEvent(tabBar.tabForItem(item2).element, which: 3) + triggerClickEvent(tabBar.tabForItem(item2).element, button: 2) expect(atom.workspace.getCenter().getPanes().length).toBe 1 atom.commands.dispatch(tabBar.element, 'tabs:split-down') @@ -614,7 +609,7 @@ describe "TabBarView", -> describe "when tabs:split-left is fired", -> it "splits the selected tab to the left", -> - triggerClickEvent(tabBar.tabForItem(item2).element, which: 3) + triggerClickEvent(tabBar.tabForItem(item2).element, button: 2) expect(atom.workspace.getCenter().getPanes().length).toBe 1 atom.commands.dispatch(tabBar.element, 'tabs:split-left') @@ -624,7 +619,7 @@ describe "TabBarView", -> describe "when tabs:split-right is fired", -> it "splits the selected tab to the right", -> - triggerClickEvent(tabBar.tabForItem(item2).element, which: 3) + triggerClickEvent(tabBar.tabForItem(item2).element, button: 2) expect(atom.workspace.getCenter().getPanes().length).toBe 1 atom.commands.dispatch(tabBar.element, 'tabs:split-right') @@ -635,7 +630,7 @@ describe "TabBarView", -> describe "when tabs:open-in-new-window is fired", -> describe "by right-clicking on a tab", -> beforeEach -> - triggerClickEvent(tabBar.tabForItem(item1).element, which: 3) + triggerClickEvent(tabBar.tabForItem(item1).element, button: 2) expect(atom.workspace.getCenter().getPanes().length).toBe 1 spyOn(atom, 'open') @@ -1384,7 +1379,7 @@ describe "TabBarView", -> runs -> pane.activateItem(editor2) expect(tabBar.tabForItem(editor2).element.querySelector('.title')).toHaveClass 'temp' - triggerMouseEvent('dblclick', tabBar.tabForItem(editor2).element, which: 1) + triggerMouseEvent('dblclick', tabBar.tabForItem(editor2).element, button: 0) expect(tabBar.tabForItem(editor2).element.querySelector('.title')).not.toHaveClass 'temp' describe "when editing a file in pending state", -> From 6a152b5136c2e57c49e4b1cdef19c76d8b0c3433 Mon Sep 17 00:00:00 2001 From: musa Ibrahim Date: Thu, 12 Nov 2020 10:24:06 +0100 Subject: [PATCH 3/3] fix failing test --- spec/tabs-spec.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/tabs-spec.coffee b/spec/tabs-spec.coffee index 59eff769..8cf00376 100644 --- a/spec/tabs-spec.coffee +++ b/spec/tabs-spec.coffee @@ -4,7 +4,8 @@ temp = require 'temp' TabBarView = require '../lib/tab-bar-view' layout = require '../lib/layout' main = require '../lib/main' -{triggerMouseEvent, triggerClickEvent, buildDragEvents, buildDragEnterLeaveEvents, buildWheelEvent, buildWheelPlusShiftEvent} = require "./event-helpers" +{triggerMouseEvent, triggerClickEvent, buildDragEvents, buildDragEnterLeaveEvents, buildWheelEvent, buildWheelPlusShiftEvent} = require "./event-helpers.coffee" +{buildDragEnterLeaveEvents} = require "./event-helpers" describe "Tabs package main", -> centerElement = null