diff options
-rw-r--r-- | xwayland/meson.build | 1 | ||||
-rw-r--r-- | xwayland/selection.c | 95 | ||||
-rw-r--r-- | xwayland/xwm.c | 11 | ||||
-rw-r--r-- | xwayland/xwm.h | 12 |
4 files changed, 119 insertions, 0 deletions
diff --git a/xwayland/meson.build b/xwayland/meson.build index e92e042c..de05cfaa 100644 --- a/xwayland/meson.build +++ b/xwayland/meson.build @@ -1,6 +1,7 @@ lib_wlr_xwayland = static_library( 'wlr_xwayland', files( + 'selection.c', 'sockets.c', 'xwayland.c', 'xwm.c', diff --git a/xwayland/selection.c b/xwayland/selection.c new file mode 100644 index 00000000..c80e1db2 --- /dev/null +++ b/xwayland/selection.c @@ -0,0 +1,95 @@ +#include <xcb/xfixes.h> +#include "wlr/util/log.h" +#include "xwm.h" + +static void xwm_handle_selection_notify(struct wlr_xwm *xwm, xcb_generic_event_t + *event) { + wlr_log(L_DEBUG, "TODO: SELECTION NOTIFY"); +} + +static int xwm_handle_selection_property_notify(struct wlr_xwm *xwm, + xcb_generic_event_t *event) { + xcb_property_notify_event_t *property_notify = + (xcb_property_notify_event_t *) event; + + if (property_notify->window == xwm->selection_window) { + if (property_notify->state == XCB_PROPERTY_NEW_VALUE && + property_notify->atom == xwm->atoms[WL_SELECTION] && + xwm->incr) + wlr_log(L_DEBUG, "TODO: get selection"); + return 1; + } else if (property_notify->window == xwm->selection_request.requestor) { + if (property_notify->state == XCB_PROPERTY_DELETE && + property_notify->atom == xwm->selection_request.property && + xwm->incr) + wlr_log(L_DEBUG, "TODO: send selection"); + return 1; + } + + return 0; +} + +static void xwm_handle_selection_request(struct wlr_xwm *xwm, + xcb_generic_event_t *event) { + wlr_log(L_DEBUG, "TODO: SELECTION REQUEST"); + return; +} + +static int weston_wm_handle_xfixes_selection_notify(struct wlr_xwm *xwm, + xcb_generic_event_t *event) { + wlr_log(L_DEBUG, "TODO: XFIXES SELECTION NOTIFY"); + return 1; +} + + +int xwm_handle_selection_event(struct wlr_xwm *xwm, + xcb_generic_event_t *event) { + switch (event->response_type & ~0x80) { + case XCB_SELECTION_NOTIFY: + xwm_handle_selection_notify(xwm, event); + return 1; + case XCB_PROPERTY_NOTIFY: + return xwm_handle_selection_property_notify(xwm, event); + case XCB_SELECTION_REQUEST: + xwm_handle_selection_request(xwm, event); + return 1; + } + + switch (event->response_type - xwm->xfixes->first_event) { + case XCB_XFIXES_SELECTION_NOTIFY: + return weston_wm_handle_xfixes_selection_notify(xwm, event); + } + + return 0; +} + +void xwm_selection_init(struct wlr_xwm *xwm) { + uint32_t values[1], mask; + + xwm->selection_request.requestor = XCB_NONE; + + values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE; + xwm->selection_window = xcb_generate_id(xwm->xcb_conn); + xcb_create_window(xwm->xcb_conn, + XCB_COPY_FROM_PARENT, + xwm->selection_window, + xwm->screen->root, + 0, 0, + 10, 10, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + xwm->screen->root_visual, + XCB_CW_EVENT_MASK, values); + + xcb_set_selection_owner(xwm->xcb_conn, + xwm->selection_window, + xwm->atoms[CLIPBOARD_MANAGER], + XCB_TIME_CURRENT_TIME); + + mask = + XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE; + xcb_xfixes_select_selection_input(xwm->xcb_conn, xwm->selection_window, + xwm->atoms[CLIPBOARD], mask); +} diff --git a/xwayland/xwm.c b/xwayland/xwm.c index fa0522d6..39cd6362 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -43,6 +43,9 @@ const char *atom_map[ATOM_LAST] = { "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "WM_STATE", + "CLIPBOARD", + "_WL_SELECTION", + "CLIPBOARD_MANAGER", }; /* General helpers */ @@ -908,6 +911,12 @@ static int x11_event_handler(int fd, uint32_t mask, void *data) { while ((event = xcb_poll_for_event(xwm->xcb_conn))) { count++; + + if (xwm_handle_selection_event(xwm, event)) { + free(event); + continue; + } + switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { case XCB_CREATE_NOTIFY: xwm_handle_create_notify(xwm, (xcb_create_notify_event_t *)event); @@ -1332,6 +1341,8 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) { xwm_set_net_active_window(xwm, XCB_WINDOW_NONE); + xwm_selection_init(xwm); + xwm->compositor_surface_create.notify = handle_compositor_surface_create; wl_signal_add(&wlr_xwayland->compositor->events.create_surface, &xwm->compositor_surface_create); diff --git a/xwayland/xwm.h b/xwayland/xwm.h index c350b6e2..2daa4eeb 100644 --- a/xwayland/xwm.h +++ b/xwayland/xwm.h @@ -31,6 +31,9 @@ enum atom_name { _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ, WM_STATE, + CLIPBOARD, + CLIPBOARD_MANAGER, + WL_SELECTION, ATOM_LAST, }; @@ -55,6 +58,11 @@ struct wlr_xwm { xcb_render_pictformat_t render_format_id; xcb_cursor_t cursor; + // selection properties + xcb_window_t selection_window; + xcb_selection_request_event_t selection_request; + int incr; + struct wlr_xwayland_surface *focus_surface; struct wl_list surfaces; // wlr_xwayland_surface::link @@ -72,4 +80,8 @@ void xwm_destroy(struct wlr_xwm *xwm); void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y); +int xwm_handle_selection_event(struct wlr_xwm *xwm, xcb_generic_event_t *event); + +void xwm_selection_init(struct wlr_xwm *xwm); + #endif |