csd: track pointer when rendering and handling CSD button clicks

* Render button as highlighted only when pointer is above them
* Releasing the mouse button while *not* on the button does *not*
  activate the button

When pressing, and holding, a mouse button, the compositor keeps
sending motion events for the surface where the button was pressed,
even if the mouse has moved outside it.

We also don't get any surface leave/enter events.

This meant that the button was rendered as highlighted, and a click
registered, if the user pressed the mouse button while on the button,
and then moved the cursor away from the button before releasing the
button.

This patch fixes it, by checking if the current cursor coordinates
fall within the button surface.
This commit is contained in:
Daniel Eklöf 2024-08-09 08:20:59 +02:00
parent 7ec9ca2b95
commit bef613e656
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 98 additions and 12 deletions

View file

@ -2627,6 +2627,32 @@ render_csd_button_close(struct terminal *term, struct buffer *buf)
pixman_image_unref(src);
}
static bool
any_pointer_is_on_button(const struct terminal *term, enum csd_surface csd_surface)
{
if (unlikely(tll_length(term->wl->seats) == 0))
return false;
tll_foreach(term->wl->seats, it) {
const struct seat *seat = &it->item;
if (seat->mouse.x < 0)
continue;
if (seat->mouse.y < 0)
continue;
struct csd_data info = get_csd_data(term, csd_surface);
if (seat->mouse.x > info.width)
continue;
if (seat->mouse.y > info.height)
continue;
return true;
}
return false;
}
static void
render_csd_button(struct terminal *term, enum csd_surface surf_idx,
const struct csd_data *info, struct buffer *buf)
@ -2650,21 +2676,24 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx,
_color = term->conf->colors.table[4]; /* blue */
is_set = term->conf->csd.color.minimize_set;
conf_color = &term->conf->csd.color.minimize;
is_active = term->active_surface == TERM_SURF_BUTTON_MINIMIZE;
is_active = term->active_surface == TERM_SURF_BUTTON_MINIMIZE &&
any_pointer_is_on_button(term, CSD_SURF_MINIMIZE);
break;
case CSD_SURF_MAXIMIZE:
_color = term->conf->colors.table[2]; /* green */
is_set = term->conf->csd.color.maximize_set;
conf_color = &term->conf->csd.color.maximize;
is_active = term->active_surface == TERM_SURF_BUTTON_MAXIMIZE;
is_active = term->active_surface == TERM_SURF_BUTTON_MAXIMIZE &&
any_pointer_is_on_button(term, CSD_SURF_MAXIMIZE);
break;
case CSD_SURF_CLOSE:
_color = term->conf->colors.table[1]; /* red */
is_set = term->conf->csd.color.close_set;
conf_color = &term->conf->csd.color.quit;
is_active = term->active_surface == TERM_SURF_BUTTON_CLOSE;
is_active = term->active_surface == TERM_SURF_BUTTON_CLOSE &&
any_pointer_is_on_button(term, CSD_SURF_CLOSE);
break;
default: