diff --git a/app/client/components/Selector.js b/app/client/components/Selector.js index ca827a8b..96471bc6 100644 --- a/app/client/components/Selector.js +++ b/app/client/components/Selector.js @@ -19,6 +19,7 @@ var ko = require('knockout'); var _ = require('underscore'); var dispose = require('../lib/dispose'); var gutil = require('app/common/gutil'); +const {isWin} = require('app/client/lib/browserInfo') var ROW = 'row'; var COL = 'col'; @@ -53,6 +54,7 @@ function Selector(view, opt) { opt = opt || {}; this.isDisabled = opt.isDisabled || _.constant(false); + this.isWindows = isWin(); } /** @@ -118,6 +120,17 @@ Selector.prototype.applyCallbacks = function(dragOrSelect, callbacks, mouseDownE callbacks.mousedown[dragOrSelect].call(this.view, mouseDownElem, mouseDownEvent); this.view.onEvent(callbacks.mousemove.source, 'mousemove', function(elem, event) { + // On windows, when browser doesn't have focus, the first click produces artificial mousemove + // event. Fortunately, the mousemove event has the same coordinates as the mousedown event, so + // we will ignore it. + // Related issues: + // https://bugs.chromium.org/p/chromium/issues/detail?id=161464 + // https://bugs.chromium.org/p/chromium/issues/detail?id=721341#c34 + if (self.isWindows) { + if (event.screenX === mouseDownEvent.screenX && event.screenY === mouseDownEvent.screenY) { + return; + } + } callbacks.mousemove[dragOrSelect].call(self.view, elem, event); }); diff --git a/app/client/lib/browserInfo.ts b/app/client/lib/browserInfo.ts index 711068cf..f20be31a 100644 --- a/app/client/lib/browserInfo.ts +++ b/app/client/lib/browserInfo.ts @@ -26,3 +26,8 @@ export function isIOS() { export function modKeyProp(): 'metaKey'|'ctrlKey' { return /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'metaKey' : 'ctrlKey'; } + +export function isWin() { + const os = getParser().getOSName(); + return os === 'Windows'; +}