Skip to content

Commit 2dd9b15

Browse files
feat: add data-tauri-drag-region="deep" (#15062)
* feat: add `data-tauri-drag-region="deep"` supersedes #6362 * Update data-tauri-drag-region-deep.md * summary is also clickable --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
1 parent eacd36a commit 2dd9b15

2 files changed

Lines changed: 68 additions & 17 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": minor:feat
3+
---
4+
5+
Add `data-tauri-drag-region="deep"` so clicks on non-clickable children will drag as well. Can still opt out of drag on some regions using `data-tauri-drag-region="false"`

crates/tauri/src/window/scripts/drag.js

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,78 @@
33
// SPDX-License-Identifier: MIT
44

55
;(function () {
6-
const osName = __TEMPLATE_os_name__
7-
86
//-----------------------//
97
// drag on mousedown and maximize on double click on Windows and Linux
10-
// while macOS macos maximization should be on mouseup and if the mouse
8+
// while macOS maximization should be on mouseup and if the mouse
119
// moves after the double click, it should be cancelled (see https://github.com/tauri-apps/tauri/issues/8306)
1210
//-----------------------//
1311
const TAURI_DRAG_REGION_ATTR = 'data-tauri-drag-region'
1412

13+
function isClickableElement(el) {
14+
const tag = el.tagName && el.tagName.toLowerCase()
15+
16+
return (
17+
tag === 'a'
18+
|| tag === 'button'
19+
|| tag === 'input'
20+
|| tag === 'select'
21+
|| tag === 'textarea'
22+
|| tag === 'label'
23+
|| tag === 'summary'
24+
|| (el.hasAttribute('contenteditable')
25+
&& el.getAttribute('contenteditable') !== 'false')
26+
|| (el.hasAttribute('tabindex') && el.getAttribute('tabindex') !== '-1')
27+
)
28+
}
29+
30+
// Walk the composed path from target upward. If a clickable element or a
31+
// data-tauri-drag-region="false" element is encountered, return false (don't drag).
32+
// Otherwise return true.
33+
//
34+
// Supported values for data-tauri-drag-region:
35+
// (bare / no value) → self: only direct clicks on this element trigger drag
36+
// "deep" → deep: clicks anywhere in the subtree trigger drag
37+
// "false" → disabled: drag is blocked here (and for ancestors)
38+
function isDragRegion(composedPath) {
39+
for (const el of composedPath) {
40+
if (!(el instanceof HTMLElement)) continue
41+
42+
// if we hit a clickable element or a disabled drag region, don't drag
43+
if (
44+
isClickableElement(el)
45+
|| el.getAttribute(TAURI_DRAG_REGION_ATTR) === 'false'
46+
) {
47+
return false
48+
}
49+
50+
const attr = el.getAttribute(TAURI_DRAG_REGION_ATTR)
51+
if (attr !== null) {
52+
// deep: the whole subtree is a drag region
53+
if (attr === 'deep') return true
54+
// bare (or any unrecognized value): self-only
55+
if (el === composedPath[0]) return true
56+
// click was on a child of a self-only region — stop walking, don't drag
57+
return false
58+
}
59+
}
60+
61+
return false
62+
}
63+
64+
const osName = __TEMPLATE_os_name__
65+
1566
// initial mousedown position for macOS
1667
let initialX = 0
1768
let initialY = 0
1869

1970
document.addEventListener('mousedown', (e) => {
20-
const attr = e.target.getAttribute(TAURI_DRAG_REGION_ATTR)
2171
if (
22-
// element has the magic data attribute
23-
attr !== null
24-
// and not false
25-
&& attr !== 'false'
26-
// and was left mouse button
27-
&& e.button === 0
72+
// was left mouse button
73+
e.button === 0
2874
// and was normal click to drag or double click to maximize
2975
&& (e.detail === 1 || e.detail === 2)
76+
// and is drag region
77+
&& isDragRegion(e.composedPath())
3078
) {
3179
// macOS maximization happens on `mouseup`,
3280
// so we save needed state and early return
@@ -48,23 +96,21 @@
4896
window.__TAURI_INTERNALS__.invoke('plugin:window|' + cmd)
4997
}
5098
})
99+
51100
// on macOS we maximize on mouseup instead, to match the system behavior where maximization can be canceled
52101
// if the mouse moves outside the data-tauri-drag-region
53102
if (osName === 'macos') {
54103
document.addEventListener('mouseup', (e) => {
55-
const attr = e.target.getAttribute(TAURI_DRAG_REGION_ATTR)
56104
if (
57-
// element has the magic data attribute
58-
attr !== null
59-
// and not false
60-
&& attr !== 'false'
61-
// and was left mouse button
62-
&& e.button === 0
105+
// was left mouse button
106+
e.button === 0
63107
// and was double click
64108
&& e.detail === 2
65109
// and the cursor hasn't moved from initial mousedown
66110
&& e.clientX === initialX
67111
&& e.clientY === initialY
112+
// and the event path contains a drag region (with no clickable element in between)
113+
&& isDragRegion(e.composedPath())
68114
) {
69115
window.__TAURI_INTERNALS__.invoke(
70116
'plugin:window|internal_toggle_maximize'

0 commit comments

Comments
 (0)