Skip to content

Clicking outside a Dropdown does not always close it #58

Description

@Vmarcelo49

Clicking outside an open dropdown usually closes it, but not when the pointer leaves the button and the press arrive in the same update.

The press is handled twice in the same input callback. The "click outside to close" block sets open = false, and the toggle block right below then sees the state it has just changed, so it reopens the popup:

https://github.com/ebitengine/debugui/blob/85357fb/dropdown.go#L74-L89

Instrumenting that callback shows it:

CB enter: open=true focusIsID=true justPressed=true
  CLOSE OUTSIDE -> open=false
  TOGGLE -> open=true          <-- reopened in the same update

c.focus is still the dropdown's ID on that update because handleInputForWidget clears the focus only when the pointer is not over the widget, and then sets it again from a stale c.hover: the else if !hover branch that would clear c.hover is skipped when justPressed is true.

With a mouse this needs the pointer to leave the button and the press to land in the same update (16ms at the default 60 TPS), so it is intermittent, but any input that jumps has the same shape. With ebiten.SetTPS(10) the window is 100ms and it reproduces easily:

  • pointer outside the button for at least one update, then press: the popup closes
  • pointer leaves and presses in the same update: the popup stays open

I see two ways to fix it.

The cause, in handleInputForWidget (this changes the behaviour of every widget, not just the dropdown; the whole test suite passes with it):

if hover && c.pointing.justPressed() {
	c.setFocus(id)
} else if c.hover == id && !hover {
	c.hover = widgetID{}
}

Or locally in the dropdown, by not letting the same press be handled as a toggle after it closed the popup:

		closedOutside := false
		if dropdownContainer.open && c.pointing.justPressed() {
			...
			if !clickInButton && !clickInDropdown {
				// Only close immediately if there's no close delay active
				if !dropdownContainer.dropdownCloseTimer.active() {
					dropdownContainer.open = false
					closedOutside = true
				}
			}
		}

		if c.pointing.justPressed() && c.focus == id && !closedOutside {

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions