static void drag_grab_focus(struct wl_grab *grab, uint32_t time, struct wl_surface *surface, int32_t x, int32_t y) { struct wl_input_device *device = container_of(grab, struct wl_input_device, drag_grab); struct wl_resource *resource, *offer; if (device->drag_focus_resource) { wl_resource_post_event(device->drag_focus_resource, WL_DATA_DEVICE_LEAVE); wl_list_remove(&device->drag_focus_listener.link); device->drag_focus_resource = NULL; device->drag_focus = NULL; } if (surface) resource = find_resource(&device->drag_resource_list, surface->resource.client); if (surface && resource) { offer = wl_data_source_send_offer(device->drag_data_source, resource); wl_resource_post_event(resource, WL_DATA_DEVICE_ENTER, time, surface, x, y, offer); device->drag_focus = surface; device->drag_focus_listener.func = destroy_drag_focus; wl_list_insert(resource->destroy_listener_list.prev, &device->drag_focus_listener.link); device->drag_focus_resource = resource; grab->focus = surface; } }
static void drag_grab_focus(struct wl_pointer_grab *grab, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y) { struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab); struct wl_resource *resource, *offer = NULL; struct wl_display *display; uint32_t serial; if (seat->drag_focus_resource) { wl_data_device_send_leave(seat->drag_focus_resource); wl_list_remove(&seat->drag_focus_listener.link); seat->drag_focus_resource = NULL; seat->drag_focus = NULL; } if (!surface) return; if (!seat->drag_data_source && surface->resource.client != seat->drag_client) return; resource = find_resource(&seat->drag_resource_list, surface->resource.client); if (!resource) return; display = wl_client_get_display(resource->client); serial = wl_display_next_serial(display); if (seat->drag_data_source) offer = wl_data_source_send_offer(seat->drag_data_source, resource); wl_data_device_send_enter(resource, serial, &surface->resource, x, y, offer); seat->drag_focus = surface; seat->drag_focus_listener.notify = destroy_drag_focus; wl_signal_add(&resource->destroy_signal, &seat->drag_focus_listener); seat->drag_focus_resource = resource; grab->focus = surface; }
WL_EXPORT void wl_seat_set_selection(struct wl_seat *seat, struct wl_data_source *source, uint32_t serial) { struct wl_resource *data_device, *offer; struct wl_resource *focus = NULL; if (seat->selection_data_source && seat->selection_serial - serial < UINT32_MAX / 2) return; if (seat->selection_data_source) { seat->selection_data_source->cancel(seat->selection_data_source); wl_list_remove(&seat->selection_data_source_listener.link); seat->selection_data_source = NULL; } seat->selection_data_source = source; seat->selection_serial = serial; if (seat->keyboard) focus = seat->keyboard->focus_resource; if (focus) { data_device = find_resource(&seat->drag_resource_list, focus->client); if (data_device && source) { offer = wl_data_source_send_offer(seat->selection_data_source, data_device); wl_data_device_send_selection(data_device, offer); } else if (data_device) { wl_data_device_send_selection(data_device, NULL); } } wl_signal_emit(&seat->selection_signal, seat); if (source) { seat->selection_data_source_listener.notify = destroy_selection_data_source; wl_signal_add(&source->resource.destroy_signal, &seat->selection_data_source_listener); } }
WL_EXPORT void wl_data_device_set_keyboard_focus(struct wl_input_device *device) { struct wl_resource *data_device, *focus, *offer; struct wl_data_source *source; focus = device->keyboard_focus_resource; if (!focus) return; data_device = find_resource(&device->drag_resource_list, focus->client); if (!data_device) return; source = device->selection_data_source; if (source) { offer = wl_data_source_send_offer(source, data_device); wl_resource_post_event(data_device, WL_DATA_DEVICE_SELECTION, offer); } }
WL_EXPORT void wl_input_device_set_selection(struct wl_input_device *device, struct wl_data_source *source, uint32_t time) { struct wl_resource *data_device, *focus, *offer; struct wl_selection_listener *listener, *next; if (device->selection_data_source) { device->selection_data_source->cancel(device->selection_data_source); wl_list_remove(&device->selection_data_source_listener.link); device->selection_data_source = NULL; } device->selection_data_source = source; focus = device->keyboard_focus_resource; if (focus) { data_device = find_resource(&device->drag_resource_list, focus->client); if (data_device) { offer = wl_data_source_send_offer(device->selection_data_source, data_device); wl_resource_post_event(data_device, WL_DATA_DEVICE_SELECTION, offer); } } wl_list_for_each_safe(listener, next, &device->selection_listener_list, link) listener->func(listener, device); device->selection_data_source_listener.func = destroy_selection_data_source; wl_list_insert(source->resource.destroy_listener_list.prev, &device->selection_data_source_listener.link); }
WL_EXPORT void wl_data_device_set_keyboard_focus(struct wl_seat *seat) { struct wl_resource *data_device, *focus, *offer; struct wl_data_source *source; if (!seat->keyboard) return; focus = seat->keyboard->focus_resource; if (!focus) return; data_device = find_resource(&seat->drag_resource_list, focus->client); if (!data_device) return; source = seat->selection_data_source; if (source) { offer = wl_data_source_send_offer(source, data_device); wl_data_device_send_selection(data_device, offer); } }