input: Schedule pointer sprite repaint when cursor is set
If a cursor was set with wl_pointer.set_cursor but not in combination with an action that has the side effect of damaging the region where the cursor is positioned, it would not be drawn. This patch explicitly schedules a repaint of the pointer sprite when it is set. clickdot is updated to illustrate the bug; when moving the pointer over clickdot, the pointer is hidden. When not having moved the pointer for 500 ms it is made visible using wl_pointer.set_pointer. Signed-off-by: Jonas Ådahl <jadahl@gmail.com> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
parent
00535ce6b4
commit
16fe4dcea9
@ -31,6 +31,9 @@
|
|||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
@ -54,6 +57,10 @@ struct clickdot {
|
|||||||
} line;
|
} line;
|
||||||
|
|
||||||
int reset;
|
int reset;
|
||||||
|
|
||||||
|
struct input *cursor_timeout_input;
|
||||||
|
int cursor_timeout_fd;
|
||||||
|
struct task cursor_timeout_task;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -211,6 +218,19 @@ button_handler(struct widget *widget,
|
|||||||
widget_schedule_redraw(widget);
|
widget_schedule_redraw(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cursor_timeout_reset(struct clickdot *clickdot)
|
||||||
|
{
|
||||||
|
const long cursor_timeout = 500;
|
||||||
|
struct itimerspec its;
|
||||||
|
|
||||||
|
its.it_interval.tv_sec = 0;
|
||||||
|
its.it_interval.tv_nsec = 0;
|
||||||
|
its.it_value.tv_sec = cursor_timeout / 1000;
|
||||||
|
its.it_value.tv_nsec = (cursor_timeout % 1000) * 1000 * 1000;
|
||||||
|
timerfd_settime(clickdot->cursor_timeout_fd, 0, &its, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
motion_handler(struct widget *widget,
|
motion_handler(struct widget *widget,
|
||||||
struct input *input, uint32_t time,
|
struct input *input, uint32_t time,
|
||||||
@ -222,7 +242,10 @@ motion_handler(struct widget *widget,
|
|||||||
|
|
||||||
window_schedule_redraw(clickdot->window);
|
window_schedule_redraw(clickdot->window);
|
||||||
|
|
||||||
return CURSOR_LEFT_PTR;
|
cursor_timeout_reset(clickdot);
|
||||||
|
clickdot->cursor_timeout_input = input;
|
||||||
|
|
||||||
|
return CURSOR_BLANK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -244,6 +267,21 @@ leave_handler(struct widget *widget,
|
|||||||
clickdot->reset = 1;
|
clickdot->reset = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cursor_timeout_func(struct task *task, uint32_t events)
|
||||||
|
{
|
||||||
|
struct clickdot *clickdot =
|
||||||
|
container_of(task, struct clickdot, cursor_timeout_task);
|
||||||
|
uint64_t exp;
|
||||||
|
|
||||||
|
if (read(clickdot->cursor_timeout_fd, &exp, sizeof (uint64_t)) !=
|
||||||
|
sizeof(uint64_t))
|
||||||
|
abort();
|
||||||
|
|
||||||
|
input_set_pointer_image(clickdot->cursor_timeout_input,
|
||||||
|
CURSOR_LEFT_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
static struct clickdot *
|
static struct clickdot *
|
||||||
clickdot_create(struct display *display)
|
clickdot_create(struct display *display)
|
||||||
{
|
{
|
||||||
@ -276,12 +314,22 @@ clickdot_create(struct display *display)
|
|||||||
clickdot->line.old_y = -1;
|
clickdot->line.old_y = -1;
|
||||||
clickdot->reset = 0;
|
clickdot->reset = 0;
|
||||||
|
|
||||||
|
clickdot->cursor_timeout_fd =
|
||||||
|
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||||
|
clickdot->cursor_timeout_task.run = cursor_timeout_func;
|
||||||
|
display_watch_fd(window_get_display(clickdot->window),
|
||||||
|
clickdot->cursor_timeout_fd,
|
||||||
|
EPOLLIN, &clickdot->cursor_timeout_task);
|
||||||
|
|
||||||
return clickdot;
|
return clickdot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clickdot_destroy(struct clickdot *clickdot)
|
clickdot_destroy(struct clickdot *clickdot)
|
||||||
{
|
{
|
||||||
|
display_unwatch_fd(window_get_display(clickdot->window),
|
||||||
|
clickdot->cursor_timeout_fd);
|
||||||
|
close(clickdot->cursor_timeout_fd);
|
||||||
if (clickdot->buffer)
|
if (clickdot->buffer)
|
||||||
cairo_surface_destroy(clickdot->buffer);
|
cairo_surface_destroy(clickdot->buffer);
|
||||||
widget_destroy(clickdot->widget);
|
widget_destroy(clickdot->widget);
|
||||||
|
@ -1665,8 +1665,10 @@ pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
|
|||||||
pointer->hotspot_x = x;
|
pointer->hotspot_x = x;
|
||||||
pointer->hotspot_y = y;
|
pointer->hotspot_y = y;
|
||||||
|
|
||||||
if (surface->buffer_ref.buffer)
|
if (surface->buffer_ref.buffer) {
|
||||||
pointer_cursor_surface_configure(surface, 0, 0);
|
pointer_cursor_surface_configure(surface, 0, 0);
|
||||||
|
weston_view_schedule_repaint(pointer->sprite);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user