mirror of
https://gitlab.freedesktop.org/wayland/weston
synced 2024-10-03 10:19:14 +00:00
window: Implement animated cursors (using pointer surfaces)
Since the introduction of pointer.set_cursor(), it is possible for a client to set the surface containing the pointer image and get frame callbacks on it thus allowing a clear implementation of animated cursors. This also makes the busy cursor hack of using frame callbacks on the busy surface unnecessary.
This commit is contained in:
parent
37ffc3c14b
commit
80620076fc
|
@ -767,42 +767,10 @@ background_create(struct desktop *desktop)
|
|||
return background;
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener busy_cursor_listener;
|
||||
|
||||
static void
|
||||
busy_cursor_frame_callback(void *data,
|
||||
struct wl_callback *callback, uint32_t time)
|
||||
{
|
||||
struct input *input = data;
|
||||
struct display *display = input_get_display(input);
|
||||
struct desktop *desktop = display_get_user_data(display);
|
||||
struct wl_surface *surface;
|
||||
int index;
|
||||
|
||||
if (callback)
|
||||
wl_callback_destroy(callback);
|
||||
if (input_get_focus_widget(input) != desktop->busy_widget)
|
||||
return;
|
||||
|
||||
/* FIXME: Get frame duration and number of frames from cursor. */
|
||||
index = (time / 100) % 8;
|
||||
input_set_pointer_image_index(input, CURSOR_WATCH, index);
|
||||
|
||||
surface = window_get_wl_surface(desktop->busy_window);
|
||||
callback = wl_surface_frame(surface);
|
||||
wl_callback_add_listener(callback, &busy_cursor_listener, input);
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener busy_cursor_listener = {
|
||||
busy_cursor_frame_callback
|
||||
};
|
||||
|
||||
static int
|
||||
busy_surface_enter_handler(struct widget *widget, struct input *input,
|
||||
float x, float y, void *data)
|
||||
{
|
||||
busy_cursor_frame_callback(input, NULL, 0);
|
||||
|
||||
return CURSOR_WATCH;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,6 +189,8 @@ struct input {
|
|||
struct window *pointer_focus;
|
||||
struct window *keyboard_focus;
|
||||
int current_cursor;
|
||||
uint32_t cursor_anim_start;
|
||||
struct wl_callback *cursor_frame_cb;
|
||||
struct wl_surface *pointer_surface;
|
||||
uint32_t modifiers;
|
||||
uint32_t pointer_enter_serial;
|
||||
|
@ -2274,14 +2276,14 @@ static const struct wl_data_device_listener data_device_listener = {
|
|||
data_device_selection
|
||||
};
|
||||
|
||||
void
|
||||
input_set_pointer_image_index(struct input *input, int pointer, int index)
|
||||
static void
|
||||
input_set_pointer_image_index(struct input *input, int index)
|
||||
{
|
||||
struct wl_buffer *buffer;
|
||||
struct wl_cursor *cursor;
|
||||
struct wl_cursor_image *image;
|
||||
|
||||
cursor = input->display->cursors[pointer];
|
||||
cursor = input->display->cursors[input->current_cursor];
|
||||
if (!cursor)
|
||||
return;
|
||||
|
||||
|
@ -2295,7 +2297,6 @@ input_set_pointer_image_index(struct input *input, int pointer, int index)
|
|||
if (!buffer)
|
||||
return;
|
||||
|
||||
input->current_cursor = pointer;
|
||||
wl_pointer_set_cursor(input->pointer, input->display->serial,
|
||||
input->pointer_surface,
|
||||
image->hotspot_x, image->hotspot_y);
|
||||
|
@ -2304,13 +2305,61 @@ input_set_pointer_image_index(struct input *input, int pointer, int index)
|
|||
image->width, image->height);
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener pointer_surface_listener;
|
||||
|
||||
static void
|
||||
pointer_surface_frame_callback(void *data, struct wl_callback *callback,
|
||||
uint32_t time)
|
||||
{
|
||||
struct input *input = data;
|
||||
struct wl_cursor *cursor =
|
||||
input->display->cursors[input->current_cursor];
|
||||
int i;
|
||||
|
||||
if (callback) {
|
||||
assert(callback == input->cursor_frame_cb);
|
||||
wl_callback_destroy(callback);
|
||||
input->cursor_frame_cb = NULL;
|
||||
}
|
||||
|
||||
if (input->current_cursor == CURSOR_UNSET)
|
||||
return;
|
||||
|
||||
/* FIXME We don't have the current time on the first call so we set
|
||||
* the animation start to the time of the first frame callback. */
|
||||
if (time == 0)
|
||||
input->cursor_anim_start = 0;
|
||||
else if (input->cursor_anim_start == 0)
|
||||
input->cursor_anim_start = time;
|
||||
|
||||
if (time == 0 || input->cursor_anim_start == 0)
|
||||
i = 0;
|
||||
else
|
||||
i = wl_cursor_frame(cursor, time - input->cursor_anim_start);
|
||||
|
||||
input_set_pointer_image_index(input, i);
|
||||
|
||||
if (cursor->image_count == 1)
|
||||
return;
|
||||
|
||||
input->cursor_frame_cb = wl_surface_frame(input->pointer_surface);
|
||||
wl_callback_add_listener(input->cursor_frame_cb,
|
||||
&pointer_surface_listener, input);
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener pointer_surface_listener = {
|
||||
pointer_surface_frame_callback
|
||||
};
|
||||
|
||||
void
|
||||
input_set_pointer_image(struct input *input, int pointer)
|
||||
{
|
||||
if (pointer == input->current_cursor)
|
||||
return;
|
||||
|
||||
input_set_pointer_image_index(input, pointer, 0);
|
||||
input->current_cursor = pointer;
|
||||
if (!input->cursor_frame_cb)
|
||||
pointer_surface_frame_callback(input, NULL, 0);
|
||||
}
|
||||
|
||||
struct wl_data_device *
|
||||
|
|
|
@ -367,9 +367,6 @@ frame_create(struct window *window, void *data);
|
|||
void
|
||||
input_set_pointer_image(struct input *input, int pointer);
|
||||
|
||||
void
|
||||
input_set_pointer_image_index(struct input *input, int pointer, int index);
|
||||
|
||||
void
|
||||
input_get_position(struct input *input, int32_t *x, int32_t *y);
|
||||
|
||||
|
|
Loading…
Reference in a new issue