diff --git a/CHANGELOG.md b/CHANGELOG.md
index 531fe89387b9d008b17a44b1e7154e46ffee7654..336e7c0ce53e0ded027658aafc714248c37b4186 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Fix occlusion artefact with non-canvas viewport and pixel-ratio > 1
 - Update nodejs-shims conditionals to handle polyfilled document object in NodeJS environment.
 - Ensure marking edges are at least one pixel wide
+- Only trigger marking when mouse is directly over canvas
 - Fix blurry occlusion in screenshots
 
 ## [v3.31.4] - 2023-02-24
diff --git a/src/mol-canvas3d/helper/interaction-events.ts b/src/mol-canvas3d/helper/interaction-events.ts
index 30145c9518d493eee6a7498a9fb96c33c3e70872..7afcabe63c1c224c8a2fd3a5b590e68d628f8fd7 100644
--- a/src/mol-canvas3d/helper/interaction-events.ts
+++ b/src/mol-canvas3d/helper/interaction-events.ts
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -197,8 +197,12 @@ export class Canvas3dInteractionHelper {
             this.drag(x, y, buttons, button, modifiers);
         });
 
-        input.move.subscribe(({ x, y, inside, buttons, button, modifiers }) => {
+        input.move.subscribe(({ x, y, inside, buttons, button, modifiers, onElement }) => {
             if (!inside || this.isInteracting) return;
+            if (!onElement) {
+                this.leave();
+                return;
+            }
             // console.log('move');
             this.move(x, y, buttons, button, modifiers);
         });
diff --git a/src/mol-plugin-ui/controls.tsx b/src/mol-plugin-ui/controls.tsx
index 44f9e9a712a66ce7a72049fb2a261613252fcb6f..2aa8241cd02e46abded13939548073bb9ed75304 100644
--- a/src/mol-plugin-ui/controls.tsx
+++ b/src/mol-plugin-ui/controls.tsx
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -240,14 +240,9 @@ export class SelectionViewportControls extends PluginUIComponent {
         this.subscribe(this.plugin.behaviors.interaction.selectionMode, () => this.forceUpdate());
     }
 
-    onMouseMove = (e: React.MouseEvent) => {
-        // ignore mouse moves when no button is held
-        if (e.buttons === 0) e.stopPropagation();
-    };
-
     render() {
         if (!this.plugin.selectionMode) return null;
-        return <div className='msp-selection-viewport-controls' onMouseMove={this.onMouseMove}>
+        return <div className='msp-selection-viewport-controls'>
             <StructureSelectionActionsControls />
         </div>;
     }
diff --git a/src/mol-plugin-ui/viewport.tsx b/src/mol-plugin-ui/viewport.tsx
index 6d0c45df7796b782868ff32292dacb549def7b38..0dff3983fb17f77158a2456548ddeb34f6e1dc19 100644
--- a/src/mol-plugin-ui/viewport.tsx
+++ b/src/mol-plugin-ui/viewport.tsx
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author David Sehnal <david.sehnal@gmail.com>
@@ -76,13 +76,8 @@ export class ViewportControls extends PluginUIComponent<ViewportControlsProps, V
         return <IconButton svg={icon} toggleState={isOn} onClick={onClick} title={title} style={{ background: 'transparent' }} />;
     }
 
-    onMouseMove = (e: React.MouseEvent) => {
-        // ignore mouse moves when no button is held
-        if (e.buttons === 0) e.stopPropagation();
-    };
-
     render() {
-        return <div className={'msp-viewport-controls'} onMouseMove={this.onMouseMove}>
+        return <div className={'msp-viewport-controls'}>
             <div className='msp-viewport-controls-buttons'>
                 <div>
                     <div className='msp-semi-transparent-background' />
diff --git a/src/mol-util/input/input-observer.ts b/src/mol-util/input/input-observer.ts
index f83b7e11a68c8ecfc9c766b19fa76a4bacf51478..d5455f0c450a627321d71d5c91b7d4f0b4f0d61d 100644
--- a/src/mol-util/input/input-observer.ts
+++ b/src/mol-util/input/input-observer.ts
@@ -163,6 +163,9 @@ export type MoveInput = {
     pageX: number,
     pageY: number,
     inside: boolean,
+    // Move is subscribed to window element
+    // This indicates that the event originated from the element the InputObserver was created on
+    onElement: boolean
 } & BaseInput
 
 export type PinchInput = {
@@ -202,6 +205,7 @@ type PointerEvent = {
     clientY: number
     pageX: number
     pageY: number
+    target: EventTarget | null
 
     preventDefault?: () => void
 }
@@ -446,7 +450,8 @@ namespace InputObserver {
                 clientX: (t0.clientX + t1.clientX) / 2,
                 clientY: (t0.clientY + t1.clientY) / 2,
                 pageX: (t0.pageX + t1.pageX) / 2,
-                pageY: (t0.pageY + t1.pageY) / 2
+                pageY: (t0.pageY + t1.pageY) / 2,
+                target: ev.target
             };
         }
 
@@ -592,7 +597,7 @@ namespace InputObserver {
             const { pageX, pageY } = ev;
             const [x, y] = pointerEnd;
             const inside = insideBounds(pointerEnd);
-            move.next({ x, y, pageX, pageY, buttons, button, modifiers: getModifierKeys(), inside });
+            move.next({ x, y, pageX, pageY, buttons, button, modifiers: getModifierKeys(), inside, onElement: ev.target === element });
 
             if (dragging === DraggingState.Stopped) return;