Skip to content

Commit 2ee100b

Browse files
andreakarashoclaude
andcommitted
Fix drag widgets using mouse release instead of mouse press
ShouldProcessClick fires on mouse release, which is correct for buttons but wrong for drag-initiated widgets (sliders, splitters, dock splitters, dock tab drag). Changed these to use IsMouseJustPressed so the drag actually runs while the mouse is held down. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e8f1bf7 commit 2ee100b

1 file changed

Lines changed: 26 additions & 7 deletions

File tree

src/Clay/ClayUI.cs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,11 @@ private static void UpdateActiveScrollbar()
768768
/// </summary>
769769
public static bool IsMouseJustPressed => _context.MousePressed && !_context.MouseWasPressed;
770770

771+
/// <summary>
772+
/// Returns true if the mouse was just released (mouse was down, now up).
773+
/// </summary>
774+
public static bool IsMouseJustReleased => !_context.MousePressed && _context.MouseWasPressed;
775+
771776
/// <summary>
772777
/// Returns true if the mouse is currently over any open window.
773778
/// Use this to block input to elements behind windows.
@@ -845,14 +850,15 @@ private static bool IsCurrentWindowTopmost
845850

846851
/// <summary>
847852
/// Returns true if a click should be processed for this widget.
853+
/// Triggers on mouse release (matching UO's button behavior).
848854
/// Widgets inside topmost windows process clicks; widgets outside are blocked if mouse is over any window.
849855
/// Widgets behind open popups are blocked unless the widget is inside the popup.
850856
/// </summary>
851857
private static bool ShouldProcessClick
852858
{
853859
get
854860
{
855-
if (!IsMouseJustPressed) return false;
861+
if (!IsMouseJustReleased) return false;
856862

857863
// Block all interaction in disabled regions
858864
if (IsDisabled) return false;
@@ -942,11 +948,14 @@ public static bool Button(string label, ButtonStyle? style = null, ButtonSkin? s
942948
Image = skinImg.HasImage ? SkinToImageConfig(skinImg) : default
943949
}))
944950
{
951+
var textFontSize = (isHovered && s.HasHoverFontSize) ? s.HoverFontSize : s.FontSize;
952+
var textColor = (isHovered && s.HasHoverTextColor) ? s.HoverTextColor : s.TextColor;
953+
945954
Clay.Text(ElementId.GetDisplayLabel(label), new TextConfig
946955
{
947956
FontId = s.FontId,
948-
FontSize = s.FontSize,
949-
TextColor = DisabledColor(s.TextColor)
957+
FontSize = textFontSize,
958+
TextColor = DisabledColor(textColor)
950959
});
951960
}
952961

@@ -1161,7 +1170,7 @@ public static bool Slider(string label, ref float value, float min = 0f, float m
11611170
var trackData = Clay.GetElementData(trackId);
11621171

11631172
// Check if this slider should become active (mouse just pressed on it)
1164-
if (isHovered && ShouldProcessClick && trackData.Found)
1173+
if (isHovered && IsMouseJustPressed && trackData.Found)
11651174
{
11661175
_context.ActiveSliderTrackId = trackId.Id;
11671176
_context.ActiveSliderMin = min;
@@ -1508,7 +1517,7 @@ public static bool Splitter(string label, ref float size1, ref float size2,
15081517
var s = style.HasValue ? style.Value.MergeOver(Style.Splitter) : Style.Splitter;
15091518
var id = StableId(label);
15101519
bool isHovered = !IsDisabled && Clay.PointerOver(id);
1511-
bool justPressed = isHovered && ShouldProcessClick;
1520+
bool justPressed = isHovered && IsMouseJustPressed;
15121521

15131522
if (isHovered) _context.HoveredThisFrame.Add(id.Id);
15141523

@@ -3092,7 +3101,7 @@ private static void RenderDockLeafTabBar(DockNode leaf, DockSpaceState space, Do
30923101
bool isHovered = !IsDisabled && Clay.PointerOver(tabId);
30933102

30943103
// Handle tab click / drag start
3095-
if (isHovered && ShouldProcessClick)
3104+
if (isHovered && IsMouseJustPressed)
30963105
{
30973106
leaf.ActiveTabIndex = i;
30983107
isActive = true;
@@ -3470,7 +3479,7 @@ private static void EmitDockSplitter(DockNode parentNode, DockSpaceStyle s)
34703479
var splitterId = ElementId.HashComposite("DockSplitter_", parentNode.Id);
34713480

34723481
bool isHovered = !IsDisabled && Clay.PointerOver(splitterId);
3473-
bool justPressed = isHovered && ShouldProcessClick;
3482+
bool justPressed = isHovered && IsMouseJustPressed;
34743483

34753484
if (justPressed)
34763485
{
@@ -6536,6 +6545,12 @@ public ButtonStyle() { }
65366545
private Sizing _sizing;
65376546
public Sizing Sizing { get => _sizing; set { _sizing = value; _set |= 1u << 8; } }
65386547

6548+
private ushort _hoverFontSize;
6549+
public ushort HoverFontSize { get => _hoverFontSize; set { _hoverFontSize = value; _set |= 1u << 9; } }
6550+
6551+
private Color _hoverTextColor;
6552+
public Color HoverTextColor { get => _hoverTextColor; set { _hoverTextColor = value; _set |= 1u << 10; } }
6553+
65396554
public ButtonStyle MergeOver(ButtonStyle @base)
65406555
{
65416556
var result = @base;
@@ -6548,11 +6563,15 @@ public ButtonStyle MergeOver(ButtonStyle @base)
65486563
if ((_set & (1u << 6)) != 0) result._fontId = _fontId;
65496564
if ((_set & (1u << 7)) != 0) result._fontSize = _fontSize;
65506565
if ((_set & (1u << 8)) != 0) result._sizing = _sizing;
6566+
if ((_set & (1u << 9)) != 0) result._hoverFontSize = _hoverFontSize;
6567+
if ((_set & (1u << 10)) != 0) result._hoverTextColor = _hoverTextColor;
65516568
result._set = @base._set | _set;
65526569
return result;
65536570
}
65546571

65556572
internal bool HasSizing => (_set & (1u << 8)) != 0;
6573+
internal bool HasHoverFontSize => (_set & (1u << 9)) != 0;
6574+
internal bool HasHoverTextColor => (_set & (1u << 10)) != 0;
65566575
}
65576576

65586577
public struct ImageStyle

0 commit comments

Comments
 (0)