struct wlr_keyboard_group *keyboard_group;
struct wlr_cursor *cursor;
struct wlr_xcursor_manager *xcursor_manager;
+ struct wlr_drag_icon *drag_icon;
/* if set, views cannot receive focus */
struct wlr_layer_surface_v1 *focused_layer;
struct wl_listener keyboard_key;
struct wl_listener keyboard_modifiers;
+
+ struct wl_listener request_start_drag;
+ struct wl_listener start_drag;
+ struct wl_listener destroy_drag;
};
struct server {
event->serial);
}
+static void
+request_start_drag_notify(struct wl_listener *listener, void *data)
+{
+ struct seat *seat = wl_container_of(
+ listener, seat, request_start_drag);
+ struct wlr_seat_request_start_drag_event *event = data;
+ if (wlr_seat_validate_pointer_grab_serial(seat->seat, event->origin, event->serial)) {
+ wlr_seat_start_pointer_drag(seat->seat, event->drag, event->serial);
+ } else {
+ wlr_data_source_destroy(event->drag->source);
+ }
+}
+
static void
process_cursor_move(struct server *server, uint32_t time)
{
* the pointer over a window.
*/
wlr_seat_pointer_notify_enter(wlr_seat, surface, sx, sy);
- if (!focus_changed) {
+ if (!focus_changed || server->seat.drag_icon) {
/*
* The enter event contains coordinates, so we only need
* to notify on motion if the focus did not change.
}
}
+void
+start_drag(struct wl_listener *listener, void *data)
+{
+ struct seat *seat = wl_container_of(listener, seat, start_drag);
+ struct wlr_drag *wlr_drag = data;
+ seat->drag_icon = wlr_drag->icon;
+ wl_signal_add(&seat->drag_icon->events.destroy, &seat->destroy_drag);
+}
+
static void
cursor_motion(struct wl_listener *listener, void *data)
{
process_cursor_motion(seat->server, event->time_msec);
}
+void
+destroy_drag(struct wl_listener *listener, void *data)
+{
+ struct seat *seat = wl_container_of(listener, seat, destroy_drag);
+
+ if (!seat->drag_icon) {
+ return;
+ }
+ seat->drag_icon = NULL;
+ desktop_focus_topmost_mapped_view(seat->server);
+}
+
void
cursor_motion_absolute(struct wl_listener *listener, void *data)
{
seat->request_set_selection.notify = request_set_selection_notify;
wl_signal_add(&seat->seat->events.request_set_selection,
&seat->request_set_selection);
+ seat->request_start_drag.notify = request_start_drag_notify;
+ wl_signal_add(&seat->seat->events.request_start_drag,
+ &seat->request_start_drag);
+ seat->start_drag.notify = start_drag;
+ wl_signal_add(&seat->seat->events.start_drag,
+ &seat->start_drag);
+ seat->destroy_drag.notify = destroy_drag;
seat->request_set_primary_selection.notify =
request_set_primary_selection_notify;
render_texture(wlr_output, output_damage, texture, box, matrix);
}
+void
+output_drag_icon_for_each_surface(struct output *output, struct seat *seat,
+ surface_iterator_func_t iterator, void *user_data)
+{
+ if (!seat->drag_icon || !seat->drag_icon->mapped) {
+ return;
+ }
+ output_surface_for_each_surface(output, seat->drag_icon->surface,
+ seat->cursor->x, seat->cursor->y, iterator, user_data);
+}
+
+static void
+render_drag_icon(struct output *output, pixman_region32_t *damage)
+{
+ struct render_data data = {
+ .damage = damage,
+ };
+ output_drag_icon_for_each_surface(output, &output->server->seat, render_surface_iterator, &data);
+}
+
#if HAVE_XWAYLAND
void
output_unmanaged_for_each_surface(struct output *output,
output_layer_for_each_surface(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
iterator, user_data);
+ output_drag_icon_for_each_surface(output, &output->server->seat, iterator, user_data);
}
struct send_frame_done_data {
render_osd(output, damage, output->server);
}
+ render_drag_icon(output, damage);
+
render_layer_toplevel(output, damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
render_layer_toplevel(output, damage,