xwayland: create DND window, add DND atom helpers

This commit is contained in:
emersion 2018-03-27 12:04:37 -04:00
parent ac715969ac
commit b6c1760de5
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
3 changed files with 88 additions and 4 deletions

View file

@ -53,6 +53,20 @@ enum atom_name {
NET_WM_WINDOW_TYPE_DROPDOWN_MENU, NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
NET_WM_WINDOW_TYPE_POPUP_MENU, NET_WM_WINDOW_TYPE_POPUP_MENU,
NET_WM_WINDOW_TYPE_COMBO, NET_WM_WINDOW_TYPE_COMBO,
DND_SELECTION,
DND_AWARE,
DND_STATUS,
DND_POSITION,
DND_ENTER,
DND_LEAVE,
DND_DROP,
DND_FINISHED,
DND_PROXY,
DND_TYPE_LIST,
DND_ACTION_MOVE,
DND_ACTION_COPY,
DND_ACTION_ASK,
DND_ACTION_PRIVATE,
ATOM_LAST, ATOM_LAST,
}; };
@ -64,6 +78,8 @@ enum net_wm_state_action {
NET_WM_STATE_TOGGLE = 2, NET_WM_STATE_TOGGLE = 2,
}; };
#define XDND_VERSION 5
struct wlr_xwm_selection { struct wlr_xwm_selection {
struct wlr_xwm *xwm; struct wlr_xwm *xwm;
xcb_atom_t atom; xcb_atom_t atom;
@ -100,6 +116,8 @@ struct wlr_xwm {
struct wlr_xwm_selection clipboard_selection; struct wlr_xwm_selection clipboard_selection;
struct wlr_xwm_selection primary_selection; struct wlr_xwm_selection primary_selection;
xcb_window_t dnd_window;
struct wlr_xwayland_surface *focus_surface; struct wlr_xwayland_surface *focus_surface;
struct wl_list surfaces; // wlr_xwayland_surface::link struct wl_list surfaces; // wlr_xwayland_surface::link

View file

@ -12,6 +12,32 @@
static const size_t incr_chunk_size = 64 * 1024; static const size_t incr_chunk_size = 64 * 1024;
static xcb_atom_t data_device_manager_dnd_action_to_atom(
struct wlr_xwm *xwm, enum wl_data_device_manager_dnd_action action) {
if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) {
return xwm->atoms[DND_ACTION_COPY];
} else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) {
return xwm->atoms[DND_ACTION_MOVE];
} else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) {
return xwm->atoms[DND_ACTION_ASK];
}
return XCB_ATOM_NONE;
}
static enum wl_data_device_manager_dnd_action
data_device_manager_dnd_action_from_atom(struct wlr_xwm *xwm,
enum atom_name atom) {
if (atom == xwm->atoms[DND_ACTION_COPY] ||
atom == xwm->atoms[DND_ACTION_PRIVATE]) {
return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
} else if (atom == xwm->atoms[DND_ACTION_MOVE]) {
return WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
} else if (atom == xwm->atoms[DND_ACTION_ASK]) {
return WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
}
return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
}
static void xwm_selection_send_notify(struct wlr_xwm_selection *selection, static void xwm_selection_send_notify(struct wlr_xwm_selection *selection,
xcb_atom_t property) { xcb_atom_t property) {
xcb_selection_notify_event_t selection_notify = { xcb_selection_notify_event_t selection_notify = {
@ -807,7 +833,8 @@ static void selection_init(struct wlr_xwm *xwm,
} }
void xwm_selection_init(struct wlr_xwm *xwm) { void xwm_selection_init(struct wlr_xwm *xwm) {
uint32_t values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; // Clipboard and primary selection
uint32_t selection_values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
xwm->selection_window = xcb_generate_id(xwm->xcb_conn); xwm->selection_window = xcb_generate_id(xwm->xcb_conn);
xcb_create_window(xwm->xcb_conn, xcb_create_window(xwm->xcb_conn,
XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT,
@ -818,7 +845,7 @@ void xwm_selection_init(struct wlr_xwm *xwm) {
0, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_INPUT_OUTPUT,
xwm->screen->root_visual, xwm->screen->root_visual,
XCB_CW_EVENT_MASK, values); XCB_CW_EVENT_MASK, selection_values);
xcb_set_selection_owner(xwm->xcb_conn, xcb_set_selection_owner(xwm->xcb_conn,
xwm->selection_window, xwm->selection_window,
@ -827,6 +854,30 @@ void xwm_selection_init(struct wlr_xwm *xwm) {
selection_init(xwm, &xwm->clipboard_selection, xwm->atoms[CLIPBOARD]); selection_init(xwm, &xwm->clipboard_selection, xwm->atoms[CLIPBOARD]);
selection_init(xwm, &xwm->primary_selection, xwm->atoms[PRIMARY]); selection_init(xwm, &xwm->primary_selection, xwm->atoms[PRIMARY]);
// Drag'n'drop
uint32_t dnd_values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
xwm->dnd_window = xcb_generate_id(xwm->xcb_conn);
xcb_create_window(xwm->xcb_conn,
XCB_COPY_FROM_PARENT,
xwm->dnd_window,
xwm->screen->root,
0, 0,
10, 10,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
xwm->screen->root_visual,
XCB_CW_EVENT_MASK, dnd_values);
uint32_t version = XDND_VERSION;
xcb_change_property(xwm->xcb_conn,
XCB_PROP_MODE_REPLACE,
xwm->dnd_window,
xwm->atoms[DND_AWARE],
XCB_ATOM_ATOM,
32,
1,
&version);
} }
void xwm_selection_finish(struct wlr_xwm *xwm) { void xwm_selection_finish(struct wlr_xwm *xwm) {
@ -836,6 +887,9 @@ void xwm_selection_finish(struct wlr_xwm *xwm) {
if (xwm->selection_window) { if (xwm->selection_window) {
xcb_destroy_window(xwm->xcb_conn, xwm->selection_window); xcb_destroy_window(xwm->xcb_conn, xwm->selection_window);
} }
if (xwm->dnd_window) {
xcb_destroy_window(xwm->xcb_conn, xwm->dnd_window);
}
if (xwm->seat) { if (xwm->seat) {
if (xwm->seat->selection_data_source && if (xwm->seat->selection_data_source &&
xwm->seat->selection_data_source->cancel == data_source_cancel) { xwm->seat->selection_data_source->cancel == data_source_cancel) {

View file

@ -56,9 +56,22 @@ const char *atom_map[ATOM_LAST] = {
"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
"_NET_WM_WINDOW_TYPE_POPUP_MENU", "_NET_WM_WINDOW_TYPE_POPUP_MENU",
"_NET_WM_WINDOW_TYPE_COMBO", "_NET_WM_WINDOW_TYPE_COMBO",
"XdndSelection",
"XdndAware",
"XdndStatus",
"XdndPosition",
"XdndEnter",
"XdndLeave",
"XdndDrop",
"XdndFinished",
"XdndProxy",
"XdndTypeList",
"XdndActionMove",
"XdndActionCopy",
"XdndActionAsk",
"XdndActionPrivate",
}; };
/* General helpers */
// TODO: replace this with hash table? // TODO: replace this with hash table?
static struct wlr_xwayland_surface *lookup_surface(struct wlr_xwm *xwm, static struct wlr_xwayland_surface *lookup_surface(struct wlr_xwm *xwm,
xcb_window_t window_id) { xcb_window_t window_id) {
@ -1531,4 +1544,3 @@ bool xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms,
return false; return false;
} }