Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid hover detection when windows are touching #18

Closed
luknw opened this issue Dec 7, 2019 · 0 comments
Closed

Invalid hover detection when windows are touching #18

luknw opened this issue Dec 7, 2019 · 0 comments

Comments

@luknw
Copy link
Contributor

luknw commented Dec 7, 2019

What?

When windows are pixel-perfect aligned one next to the other, the hover status isn't updated properly.

Minimum example

Replace the window in the default demo with the following:

if (nk_begin(ctx, "Demo1", nk_rect(100, 100, 200, 200),
    NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
    nk_layout_row_dynamic(ctx, 80, 1);
    nk_button_label(ctx, "button");
}
nk_end(ctx);
if (nk_begin(ctx, "Demo2", nk_rect(300, 100, 200, 200),
    NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
    nk_layout_row_dynamic(ctx, 80, 1);
    nk_button_label(ctx, "button");
}
nk_end(ctx);

nuklear-bug-report-bad
The left button doesn't react on hover.

When windows are spread apart by 1 or more pixels, hover works fine:

if (nk_begin(ctx, "Demo1", nk_rect(100, 100, 200, 200),
    NK_WINDOW_MOVABLE|NK_WINDOW_TITLE))
{
    nk_layout_row_dynamic(ctx, 80, 1);
    nk_button_label(ctx, "button");
}
nk_end(ctx);
if (nk_begin(ctx, "Demo2", nk_rect(300 + 1, 100, 200, 200),
    NK_WINDOW_MOVABLE|NK_WINDOW_TITLE))
{
    nk_layout_row_dynamic(ctx, 80, 1);
    nk_button_label(ctx, "button");
}
nk_end(ctx);

nuklear-bug-report-good

Suggested fix

The hover isn't updated, because windows are detected as intersecting each other:

/* activate window if hovered and no other window is overlapping this window */
inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
iter = win->next;
while (iter) {
struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
(!(iter->flags & NK_WINDOW_HIDDEN)))
break;
if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
iter->popup.win->bounds.x, iter->popup.win->bounds.y,
iter->popup.win->bounds.w, iter->popup.win->bounds.h))
break;
iter = iter->next;
}
}

The NK_INTERSECT is defined as:

Nuklear/src/nuklear.h

Lines 5405 to 5406 in adc52d7

#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
(!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))

I'd suggest to fix the off-by-one error by making the upper bound exclusive:

#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
    (!(((x1 >= (x0 + w0)) || ((x1 + w1) <= x0) || (y1 >= (y0 + h0)) || (y1 + h1) <= y0)))

This way, it would match all the other checks based on NK_BETWEEN which is also exclusive in the upper bound:

Nuklear/src/nuklear.h

Lines 5402 to 5404 in adc52d7

#define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
#define NK_INBOX(px, py, x, y, w, h)\
(NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant