Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

[WIP] xwayland: add incoming drag'n'drop support #841

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions include/wlr/types/wlr_data_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
#include <wlr/types/wlr_seat.h>

extern const struct
wlr_pointer_grab_interface wlr_data_device_pointer_drag_interface;
wlr_pointer_grab_interface wlr_data_device_pointer_drag_interface;

extern const struct
wlr_keyboard_grab_interface wlr_data_device_keyboard_drag_interface;
wlr_keyboard_grab_interface wlr_data_device_keyboard_drag_interface;

extern const struct
wlr_touch_grab_interface wlr_data_device_touch_drag_interface;
wlr_touch_grab_interface wlr_data_device_touch_drag_interface;

struct wlr_data_device_manager {
struct wl_global *global;
Expand Down Expand Up @@ -221,4 +221,8 @@ void wlr_data_source_dnd_finish(struct wlr_data_source *source);
void wlr_data_source_dnd_action(struct wlr_data_source *source,
enum wl_data_device_manager_dnd_action action);

struct wlr_drag *wlr_seat_client_start_grab(struct wlr_seat_client *client,
struct wlr_data_source *source, struct wlr_surface *icon_surface,
struct wlr_touch_point *point);

#endif
1 change: 0 additions & 1 deletion include/wlr/types/wlr_seat.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ struct wlr_seat {
// `drag` goes away before `drag_source`, when the implicit grab ends
struct wlr_drag *drag;
struct wlr_data_source *drag_source;
uint32_t drag_serial;

struct wlr_seat_pointer_state pointer_state;
struct wlr_seat_keyboard_state keyboard_state;
Expand Down
20 changes: 20 additions & 0 deletions include/xwayland/selection.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef XWAYLAND_SELECTION_H
#define XWAYLAND_SELECTION_H

#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_primary_selection.h>
#include <xcb/xfixes.h>

#define INCR_CHUNK_SIZE (64 * 1024)
Expand Down Expand Up @@ -39,6 +41,18 @@ struct wlr_xwm_selection {
struct wl_list outgoing;
};

struct wlr_xwayland_data_source {
struct wlr_data_source base;
struct wlr_xwm_selection *selection;
struct wl_array mime_types_atoms;
};

struct wlr_xwayland_primary_selection_source {
struct wlr_primary_selection_source base;
struct wlr_xwm_selection *selection;
struct wl_array mime_types_atoms;
};

void xwm_selection_transfer_remove_source(
struct wlr_xwm_selection_transfer *transfer);
void xwm_selection_transfer_close_source_fd(
Expand All @@ -63,8 +77,14 @@ int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
bool data_source_is_xwayland(struct wlr_data_source *wlr_source);
bool primary_selection_source_is_xwayland(
struct wlr_primary_selection_source *wlr_source);
struct wlr_xwayland_data_source *xwayland_data_source_create(
struct wlr_xwm_selection *selection);
struct wlr_xwayland_data_source *xwayland_data_source_from_wlr_data_source(
struct wlr_data_source *wlr_source);

void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag);
int xwm_dnd_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
xcb_xfixes_selection_notify_event_t *event);

void xwm_selection_init(struct wlr_xwm *xwm);
void xwm_selection_finish(struct wlr_xwm *xwm);
Expand Down
3 changes: 3 additions & 0 deletions include/xwayland/xwm.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ struct wlr_xwm {
struct wl_list surfaces; // wlr_xwayland_surface::link
struct wl_list unpaired_surfaces; // wlr_xwayland_surface::unpaired_link

struct wlr_drag *incoming_drag;

struct wlr_drag *drag;
struct wlr_xwayland_surface *drag_focus;

Expand All @@ -134,6 +136,7 @@ struct wlr_xwm {
struct wl_listener seat_drag_drop;
struct wl_listener seat_drag_destroy;
struct wl_listener seat_drag_source_destroy;
struct wl_listener incoming_drag_destroy;
};

struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland);
Expand Down
82 changes: 46 additions & 36 deletions types/data_device/wlr_drag.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static void drag_set_focus(struct wlr_drag *drag,
}

struct wlr_seat_client *focus_client = wlr_seat_client_for_wl_client(
drag->seat_client->seat, wl_resource_get_client(surface->resource));
drag->seat, wl_resource_get_client(surface->resource));
if (!focus_client) {
return;
}
Expand All @@ -80,8 +80,7 @@ static void drag_set_focus(struct wlr_drag *drag,
}

if (!wl_list_empty(&focus_client->data_devices)) {
uint32_t serial =
wl_display_next_serial(drag->seat_client->seat->display);
uint32_t serial = wl_display_next_serial(drag->seat->display);
struct wl_resource *resource;
wl_resource_for_each(resource, &focus_client->data_devices) {
wl_data_device_send_enter(resource, serial, surface->resource,
Expand Down Expand Up @@ -384,54 +383,33 @@ static void seat_handle_drag_source_destroy(struct wl_listener *listener,
seat->drag_source = NULL;
}

bool seat_client_start_drag(struct wlr_seat_client *client,
struct wlr_drag *wlr_seat_client_start_grab(struct wlr_seat_client *client,
struct wlr_data_source *source, struct wlr_surface *icon_surface,
struct wlr_surface *origin, uint32_t serial) {
struct wlr_touch_point *point) {
struct wlr_seat *seat = client->seat;

struct wlr_drag *drag = calloc(1, sizeof(struct wlr_drag));
if (drag == NULL) {
return false;
return NULL;
}

drag->seat = seat;
wl_signal_init(&drag->events.focus);
wl_signal_init(&drag->events.motion);
wl_signal_init(&drag->events.drop);
wl_signal_init(&drag->events.destroy);

struct wlr_seat *seat = client->seat;
drag->seat = seat;

drag->is_pointer_grab = !wl_list_empty(&client->pointers) &&
seat->pointer_state.button_count == 1 &&
seat->pointer_state.grab_serial == serial &&
seat->pointer_state.focused_surface &&
seat->pointer_state.focused_surface == origin;

bool is_touch_grab = !wl_list_empty(&client->touches) &&
wlr_seat_touch_num_points(seat) == 1 &&
seat->touch_state.grab_serial == serial;

// set in the iteration
struct wlr_touch_point *point = NULL;
if (is_touch_grab) {
wl_list_for_each(point, &seat->touch_state.touch_points, link) {
is_touch_grab = point->surface && point->surface == origin;
break;
}
}

if (!drag->is_pointer_grab && !is_touch_grab) {
free(drag);
return true;
if (point == NULL) {
drag->is_pointer_grab = true;
}

if (icon_surface) {
int32_t touch_id = (point ? point->touch_id : 0);
int32_t touch_id = point ? point->touch_id : 0;
struct wlr_drag_icon *icon =
drag_icon_create(icon_surface, client, drag->is_pointer_grab,
touch_id);
if (!icon) {
free(drag);
return false;
return NULL;
}

drag->icon = icon;
Expand All @@ -446,6 +424,7 @@ bool seat_client_start_drag(struct wlr_seat_client *client,
}

drag->seat_client = client;

drag->pointer_grab.data = drag;
drag->pointer_grab.interface = &data_device_pointer_drag_interface;

Expand All @@ -468,7 +447,6 @@ bool seat_client_start_drag(struct wlr_seat_client *client,
}

seat->drag = drag; // TODO: unset this thing somewhere
seat->drag_serial = serial;

seat->drag_source = source;
if (source != NULL) {
Expand All @@ -477,6 +455,38 @@ bool seat_client_start_drag(struct wlr_seat_client *client,
}

wlr_signal_emit_safe(&seat->events.start_drag, drag);
return drag;
}

bool seat_client_start_drag(struct wlr_seat_client *client,
struct wlr_data_source *source, struct wlr_surface *icon_surface,
struct wlr_surface *origin, uint32_t serial) {
struct wlr_seat *seat = client->seat;

bool is_pointer_grab = !wl_list_empty(&client->pointers) &&
seat->pointer_state.button_count == 1 &&
seat->pointer_state.grab_serial == serial &&
seat->pointer_state.focused_surface &&
seat->pointer_state.focused_surface == origin;

bool is_touch_grab = !wl_list_empty(&client->touches) &&
wlr_seat_touch_num_points(seat) == 1 &&
seat->touch_state.grab_serial == serial;

// set in the iteration
struct wlr_touch_point *point = NULL;
if (is_touch_grab) {
wl_list_for_each(point, &seat->touch_state.touch_points, link) {
is_touch_grab = point->surface && point->surface == origin;
break;
}
}

if (!is_pointer_grab && !is_touch_grab) {
return true;
}

return true;
struct wlr_drag *drag = wlr_seat_client_start_grab(client, source,
icon_surface, point);
return drag != NULL;
}
Loading