diff --git a/crates/tauri/Cargo.toml b/crates/tauri/Cargo.toml
index 071076fa4..874b986aa 100644
--- a/crates/tauri/Cargo.toml
+++ b/crates/tauri/Cargo.toml
@@ -240,6 +240,10 @@ path = "../../examples/commands/main.rs"
name = "helloworld"
path = "../../examples/helloworld/main.rs"
+[[example]]
+name = "drag"
+path = "../../examples/drag/main.rs"
+
[[example]]
name = "multiwebview"
path = "../../examples/multiwebview/main.rs"
diff --git a/crates/tauri/src/window/scripts/drag.js b/crates/tauri/src/window/scripts/drag.js
index 2b533549a..5a0b1244f 100644
--- a/crates/tauri/src/window/scripts/drag.js
+++ b/crates/tauri/src/window/scripts/drag.js
@@ -9,53 +9,61 @@
// moves after the double click, it should be cancelled (see https://github.com/tauri-apps/tauri/issues/8306)
//-----------------------//
const TAURI_DRAG_REGION_ATTR = 'data-tauri-drag-region'
+ const CLICKABLE_TAGS = new Set([
+ 'A',
+ 'BUTTON',
+ 'INPUT',
+ 'SELECT',
+ 'TEXTAREA',
+ 'LABEL',
+ 'SUMMARY'
+ ])
+ const INTERACTIVE_ROLES = new Set([
+ 'button',
+ 'link',
+ 'menuitem',
+ 'tab',
+ 'checkbox',
+ 'radio',
+ 'switch',
+ 'option'
+ ])
function isClickableElement(el) {
- const tag = el.tagName && el.tagName.toLowerCase()
-
return (
- tag === 'a'
- || tag === 'button'
- || tag === 'input'
- || tag === 'select'
- || tag === 'textarea'
- || tag === 'label'
- || tag === 'summary'
+ CLICKABLE_TAGS.has(el.tagName)
|| (el.hasAttribute('contenteditable')
&& el.getAttribute('contenteditable') !== 'false')
|| (el.hasAttribute('tabindex') && el.getAttribute('tabindex') !== '-1')
+ || INTERACTIVE_ROLES.has(el.getAttribute('role'))
)
}
- // Walk the composed path from target upward. If a clickable element or a
- // data-tauri-drag-region="false" element is encountered, return false (don't drag).
- // Otherwise return true.
+ // Walk the composed path from target upward.
//
// Supported values for data-tauri-drag-region:
- // (bare / no value) -> self: only direct clicks on this element trigger drag
- // "deep" -> deep: clicks anywhere in the subtree trigger drag
- // "false" -> disabled: drag is blocked here (and for ancestors)
+ // (bare / no value / "true") -> self: only direct clicks on this element trigger drag
+ // "deep" -> deep: clicks anywhere in the subtree trigger drag
+ // "false" -> disabled: drag is blocked here (and for ancestors)
+ //
+ // Clickable elements (buttons, links, etc.) normally block dragging,
+ // but if they themselves carry data-tauri-drag-region they act as drag regions.
function isDragRegion(composedPath) {
for (const el of composedPath) {
if (!(el instanceof HTMLElement)) continue
- // if we hit a clickable element or a disabled drag region, don't drag
- if (
- isClickableElement(el)
- || el.getAttribute(TAURI_DRAG_REGION_ATTR) === 'false'
- ) {
- return false
- }
-
const attr = el.getAttribute(TAURI_DRAG_REGION_ATTR)
- if (attr !== null) {
- // deep: the whole subtree is a drag region
- if (attr === 'deep') return true
- // bare (or any unrecognized value): self-only
- if (el === composedPath[0]) return true
- // click was on a child of a self-only region - stop walking, don't drag
- return false
- }
+
+ // clickable without explicit drag region → blocks drag
+ if (isClickableElement(el) && attr === null) return false
+ // no attr → keep walking up
+ if (attr === null) continue
+ // explicitly disabled
+ if (attr === 'false') return false
+ // subtree drag — any descendant triggers
+ if (attr === 'deep') return true
+ // bare or "true" attr — only direct clicks on this element
+ if (attr === '' || attr === 'true') return el === composedPath[0]
}
return false
diff --git a/examples/drag/README.md b/examples/drag/README.md
new file mode 100644
index 000000000..593d5753c
--- /dev/null
+++ b/examples/drag/README.md
@@ -0,0 +1,3 @@
+# Drag Window Example
+
+To execute run the following on the root directory of the repository: `cargo run --example drag`.
diff --git a/examples/drag/index.html b/examples/drag/index.html
new file mode 100644
index 000000000..49208b182
--- /dev/null
+++ b/examples/drag/index.html
@@ -0,0 +1,418 @@
+
+
+
+
+
+
+
+
+
+
Drag.js Paths & Configuration - QA Test Suite
+
+
+
Configuration Reference
+
+ Attribute: data-tauri-drag-region
+
+
+
+
+
Drag Region Values
+
bare / no value → self (direct clicks only)
+
"deep" → deep (subtree clicks)
+
"false" → disabled (drag blocked)
+
+
+
+
QA Test Cases - Try Dragging Each Section
+
+
+
+ 1. No Attribute (Default - Should NOT Drag)
+
+
+ No data-tauri-drag-region attribute
+
+
+
+
+
+ 2. Bare Attribute (Self Only - Should Drag Direct Click)
+