1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use fret_core::{Modifiers, Px};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct DockingInteractionSettings {
pub drag_inversion: DockDragInversionSettings,
/// Drag activation threshold for docking tab drags (window-local logical pixels).
pub tab_drag_threshold: Px,
/// Split handle hit thickness (window-local logical pixels).
///
/// Dear ImGui exposes this concept as `Style.DockingSeparatorSize` (scaled).
pub split_handle_hit_thickness: Px,
/// Split handle gap between panels (window-local logical pixels).
///
/// This is kept as an explicit knob because it affects both:
/// - the computed panel rects, and
/// - the split handle centers/hit rects.
pub split_handle_gap: Px,
/// Drag distance threshold for suppressing viewport right-click context menus (screen px).
///
/// Docking forwards viewport pointer input via `Effect::ViewportInput` and uses pointer capture
/// to keep delivering events when the cursor leaves the viewport bounds.
///
/// For editor-like viewports, it is common to support both:
/// - right-click context menus (when the pointer does not move), and
/// - right-drag navigation (orbit/pan) without a context menu on release.
///
/// When this value is exceeded during a right-button viewport capture, docking will suppress
/// bubbling on the matching `PointerUp` so context-menu primitives upstream do not trigger.
pub viewport_context_menu_drag_threshold: Px,
/// When true, suppress bubbling of secondary right-click events while a viewport capture
/// session is active (e.g. during a left-drag marquee).
pub suppress_context_menu_during_viewport_capture: bool,
/// Scale factor for the inner docking hint pad geometry (1.0 matches current ImGui-parity).
pub dock_hint_scale_inner: f32,
/// Scale factor for the outer docking hint pad geometry (1.0 matches current ImGui-parity).
pub dock_hint_scale_outer: f32,
/// Optional ImGui-style "transparent payload" behavior when a dock tear-off window is
/// following the cursor.
///
/// When enabled, the runner may:
/// - make the dock-floating OS window semi-transparent, and
/// - ignore mouse events for it ("NoInputs"), so hovered-window selection can "peek behind"
/// the moving window in overlap cases.
///
/// Default is `false` to keep multi-window behavior conservative across platforms/backends.
pub transparent_payload_during_follow: bool,
/// Optional ImGui-style "follow window" behavior during docking drags.
///
/// When enabled, docking interactions may request the runner to treat certain dock drags as a
/// "move the OS window" gesture (while still allowing cross-window hover/drop routing).
///
/// This is intentionally conservative by default: runners vary in how reliable it is to move
/// OS windows at high frequency, and the UX depends on also supporting "peek behind the moving
/// window" hover semantics.
pub follow_window_during_drag: bool,
/// Alpha multiplier for the tear-off payload window while following the cursor.
///
/// ImGui uses `0.50` for `ConfigDockingTransparentPayload`.
pub transparent_payload_alpha: f32,
}
impl Default for DockingInteractionSettings {
fn default() -> Self {
Self {
drag_inversion: DockDragInversionSettings::default(),
tab_drag_threshold: Px(6.0),
split_handle_hit_thickness: Px(6.0),
split_handle_gap: Px(0.0),
viewport_context_menu_drag_threshold: Px(6.0),
suppress_context_menu_during_viewport_capture: true,
dock_hint_scale_inner: 1.0,
dock_hint_scale_outer: 1.0,
transparent_payload_during_follow: false,
follow_window_during_drag: false,
transparent_payload_alpha: 0.5,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DockDragInversionSettings {
pub modifier: DockDragInversionModifier,
pub policy: DockDragInversionPolicy,
}
impl Default for DockDragInversionSettings {
fn default() -> Self {
Self {
modifier: DockDragInversionModifier::Shift,
policy: DockDragInversionPolicy::DockByDefault,
}
}
}
impl DockDragInversionSettings {
pub fn wants_dock_previews(self, modifiers: Modifiers) -> bool {
let modifier_down = self.modifier.is_down(modifiers);
match self.policy {
DockDragInversionPolicy::DockByDefault => !modifier_down,
DockDragInversionPolicy::DockOnlyWhenModifier => modifier_down,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DockDragInversionModifier {
None,
Shift,
Ctrl,
Alt,
AltGr,
Meta,
}
impl DockDragInversionModifier {
pub fn is_down(self, modifiers: Modifiers) -> bool {
match self {
Self::None => false,
Self::Shift => modifiers.shift,
Self::Ctrl => modifiers.ctrl,
Self::Alt => modifiers.alt,
Self::AltGr => modifiers.alt_gr,
Self::Meta => modifiers.meta,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DockDragInversionPolicy {
DockByDefault,
DockOnlyWhenModifier,
}