static void seat_pointer_warp(struct ds_seat *seat, double sx, double sy);
static void
+seat_client_send_pointer_enter_raw(struct ds_seat_client *seat_client,
+ struct ds_surface *surface, double sx, double sy);
+static void
seat_client_send_pointer_leave_raw(struct ds_seat_client *seat_client,
struct ds_surface *surface);
static void
+seat_pointer_handle_client_destroy(struct wl_listener *listener, void *data);
+static void
seat_pointer_handle_surface_destroy(struct wl_listener *listener,
void *data);
+static void seat_pointer_clear_focus(struct ds_seat_pointer *pointer);
+static void seat_pointer_set_focus_surface(struct ds_seat_pointer *pointer,
+ struct ds_surface *surface, double sx, double sy);
+static void seat_pointer_unset_focus_surface(struct ds_seat_pointer *pointer);
+static void seat_pointer_emit_focus_change(struct ds_seat_pointer *pointer,
+ struct ds_surface *old_surface, struct ds_surface *new_surface,
+ double sx, double sy);
static void pointer_handle_resource_destroy(struct wl_resource *resource);
static void pointer_send_frame(struct wl_resource *resource);
double sx, double sy)
{
struct ds_seat_pointer *pointer = &seat->pointer;
- struct ds_seat_client *seat_client = NULL, *focused_client;
- struct ds_surface *focused_surface;
- struct wl_client *wl_client;
- struct wl_resource *resource;
- uint32_t serial;
+ struct ds_surface *focused_surface = pointer->focused_surface;
- if (pointer->focused_surface == surface) {
+ if (focused_surface == surface) {
// this surface already got an enter notify
return;
}
- focused_client = pointer->focused_client;
- focused_surface = pointer->focused_surface;
-
- if (focused_client != NULL && focused_surface != NULL)
- seat_client_send_pointer_leave_raw(focused_client, focused_surface);
+ seat_pointer_unset_focus_surface(pointer);
if (surface) {
- wl_client =
- wl_resource_get_client(ds_surface_get_wl_resource(surface));
- seat_client = seat_client_for_wl_client(seat, wl_client);
- }
-
- if (seat_client) {
- serial = wl_display_next_serial(seat->display);
- wl_resource_for_each(resource, &seat_client->pointers) {
- wl_pointer_send_enter(resource, serial,
- ds_surface_get_wl_resource(surface),
- wl_fixed_from_double(sx), wl_fixed_from_double(sy));
- pointer_send_frame(resource);
- }
- }
+ seat_pointer_set_focus_surface(pointer, surface, sx, sy);
- wl_list_remove(&pointer->surface_destroy.link);
- wl_list_init(&pointer->surface_destroy.link);
-
- if (surface) {
- pointer->surface_destroy.notify =
- seat_pointer_handle_surface_destroy;
- ds_surface_add_destroy_listener(surface, &pointer->surface_destroy);
- }
-
- pointer->focused_client = seat_client;
- pointer->focused_surface = surface;
- if (surface)
seat_pointer_warp(seat, sx, sy);
- else
+ }
+ else {
seat_pointer_warp(seat, NAN, NAN);
+ }
- struct ds_event_seat_pointer_focus_change event = {
- .seat = seat,
- .new_surface = surface,
- .old_surface = focused_surface,
- .sx = sx,
- .sy = sy,
- };
- wl_signal_emit(&pointer->events.focus_change, &event);
+ seat_pointer_emit_focus_change(pointer, focused_surface, surface, sx, sy);
}
void
ds_seat_pointer_clear_focus(struct ds_seat *seat)
{
- ds_seat_pointer_enter(seat, NULL, 0, 0);
+ seat_pointer_clear_focus(&seat->pointer);
}
void
pointer->grab = grab;
pointer->seat = seat;
+ pointer->client_destroy.notify = seat_pointer_handle_client_destroy;
+ wl_list_init(&pointer->client_destroy.link);
+
+ pointer->surface_destroy.notify = seat_pointer_handle_surface_destroy;
wl_list_init(&pointer->surface_destroy.link);
wl_signal_init(&pointer->events.focus_change);
{
struct ds_seat_pointer *pointer = &seat->pointer;
- wl_list_remove(&pointer->surface_destroy.link);
+ if (pointer->focused_client)
+ wl_list_remove(&pointer->client_destroy.link);
+
+ if (pointer->focused_surface)
+ wl_list_remove(&pointer->surface_destroy.link);
+
free(pointer->default_grab);
}
}
static void
+seat_client_send_pointer_enter_raw(struct ds_seat_client *seat_client,
+ struct ds_surface *surface, double sx, double sy)
+{
+ struct wl_resource *resource;
+ uint32_t serial;
+
+ serial = wl_display_next_serial(seat_client->seat->display);
+ wl_resource_for_each(resource, &seat_client->pointers) {
+ wl_pointer_send_enter(resource, serial,
+ ds_surface_get_wl_resource(surface),
+ wl_fixed_from_double(sx), wl_fixed_from_double(sy));
+ pointer_send_frame(resource);
+ }
+}
+
+static void
seat_client_send_pointer_leave_raw(struct ds_seat_client *seat_client,
struct ds_surface *surface)
{
}
static void
+seat_pointer_handle_client_destroy(struct wl_listener *listener, void *data)
+{
+ struct ds_seat_pointer *pointer;
+
+ pointer = wl_container_of(listener, pointer, client_destroy);
+
+ wl_list_remove(&pointer->client_destroy.link);
+ pointer->focused_client = NULL;
+}
+
+static void
seat_pointer_handle_surface_destroy(struct wl_listener *listener, void *data)
{
struct ds_seat_pointer *pointer;
pointer = wl_container_of(listener, pointer, surface_destroy);
- wl_list_remove(&pointer->surface_destroy.link);
- wl_list_init(&pointer->surface_destroy.link);
- ds_seat_pointer_clear_focus(pointer->seat);
+
+ seat_pointer_clear_focus(pointer);
+}
+
+static void
+seat_pointer_clear_focus(struct ds_seat_pointer *pointer)
+{
+ struct ds_surface *focused_surface = pointer->focused_surface;
+
+ seat_pointer_unset_focus_surface(pointer);
+
+ seat_pointer_warp(pointer->seat, NAN, NAN);
+
+ if (focused_surface)
+ seat_pointer_emit_focus_change(pointer, focused_surface, NULL, 0, 0);
+}
+
+static void
+seat_pointer_set_focus_surface(struct ds_seat_pointer *pointer,
+ struct ds_surface *surface, double sx, double sy)
+{
+ struct ds_seat *seat = pointer->seat;
+ struct ds_seat_client *seat_client;
+
+ seat_client = seat_client_from_surface(seat, surface);
+ if (seat_client) {
+ seat_client_send_pointer_enter_raw(seat_client, surface, sx, sy);
+
+ wl_signal_add(&seat_client->events.destroy, &pointer->client_destroy);
+
+ pointer->focused_client = seat_client;
+ }
+
+ ds_surface_add_destroy_listener(surface, &pointer->surface_destroy);
+
+ pointer->focused_surface = surface;
+}
+
+static void
+seat_pointer_unset_focus_surface(struct ds_seat_pointer *pointer)
+{
+ struct ds_seat_client *focused_client = pointer->focused_client;
+ struct ds_surface *focused_surface = pointer->focused_surface;
+
+ if (focused_client)
+ wl_list_remove(&pointer->client_destroy.link);
+
+ if (focused_surface)
+ wl_list_remove(&pointer->surface_destroy.link);
+
+ if (focused_client != NULL && focused_surface != NULL)
+ seat_client_send_pointer_leave_raw(focused_client, focused_surface);
+
+ pointer->focused_client = NULL;
+ pointer->focused_surface = NULL;
+}
+
+static void
+seat_pointer_emit_focus_change(struct ds_seat_pointer *pointer,
+ struct ds_surface *old_surface, struct ds_surface *new_surface,
+ double sx, double sy)
+{
+ struct ds_event_seat_pointer_focus_change event = {
+ .seat = pointer->seat,
+ .new_surface = new_surface,
+ .old_surface = old_surface,
+ .sx = sx,
+ .sy = sy,
+ };
+ wl_signal_emit(&pointer->events.focus_change, &event);
}
static void