2019-03-05 23:32:24 +00:00
|
|
|
#define _POSIX_C_SOURCE 200809L
|
2018-02-12 20:29:23 +00:00
|
|
|
#include <errno.h>
|
2017-08-19 15:59:31 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <signal.h>
|
2018-02-12 20:29:23 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdlib.h>
|
2017-08-19 15:59:31 +00:00
|
|
|
#include <sys/socket.h>
|
2017-08-23 21:19:15 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
2017-08-19 15:59:31 +00:00
|
|
|
#include <time.h>
|
2018-02-12 20:29:23 +00:00
|
|
|
#include <unistd.h>
|
2022-10-14 15:53:56 +00:00
|
|
|
#include <wlr/types/wlr_seat.h>
|
2018-02-12 08:12:31 +00:00
|
|
|
#include <wlr/util/log.h>
|
2022-10-18 11:09:17 +00:00
|
|
|
#include <wlr/xwayland/shell.h>
|
2022-10-14 15:53:56 +00:00
|
|
|
#include <wlr/xwayland/xwayland.h>
|
2017-08-20 05:59:03 +00:00
|
|
|
#include "sockets.h"
|
2018-03-03 16:03:19 +00:00
|
|
|
#include "xwayland/xwm.h"
|
2017-08-19 15:59:31 +00:00
|
|
|
|
2017-11-02 15:49:22 +00:00
|
|
|
struct wlr_xwayland_cursor {
|
|
|
|
uint8_t *pixels;
|
|
|
|
uint32_t stride;
|
|
|
|
uint32_t width;
|
|
|
|
uint32_t height;
|
|
|
|
int32_t hotspot_x;
|
|
|
|
int32_t hotspot_y;
|
|
|
|
};
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
static void handle_server_destroy(struct wl_listener *listener, void *data) {
|
|
|
|
struct wlr_xwayland *xwayland =
|
|
|
|
wl_container_of(listener, xwayland, server_destroy);
|
2022-04-20 15:50:55 +00:00
|
|
|
// Server is being destroyed so avoid destroying it once again.
|
|
|
|
xwayland->server = NULL;
|
2020-05-05 08:24:08 +00:00
|
|
|
wlr_xwayland_destroy(xwayland);
|
2017-08-19 15:59:31 +00:00
|
|
|
}
|
|
|
|
|
2022-10-18 11:09:17 +00:00
|
|
|
static void handle_server_start(struct wl_listener *listener, void *data) {
|
|
|
|
struct wlr_xwayland *xwayland =
|
|
|
|
wl_container_of(listener, xwayland, server_start);
|
|
|
|
wlr_xwayland_shell_v1_set_client(xwayland->shell_v1, xwayland->server->client);
|
|
|
|
}
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
static void handle_server_ready(struct wl_listener *listener, void *data) {
|
|
|
|
struct wlr_xwayland *xwayland =
|
|
|
|
wl_container_of(listener, xwayland, server_ready);
|
|
|
|
struct wlr_xwayland_server_ready_event *event = data;
|
2017-12-08 00:38:45 +00:00
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
xwayland->xwm = xwm_create(xwayland, event->wm_fd);
|
|
|
|
if (!xwayland->xwm) {
|
2018-05-06 22:43:26 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
if (xwayland->seat) {
|
|
|
|
xwm_set_seat(xwayland->xwm, xwayland->seat);
|
2017-11-22 13:23:23 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
if (xwayland->cursor != NULL) {
|
|
|
|
struct wlr_xwayland_cursor *cur = xwayland->cursor;
|
|
|
|
xwm_set_cursor(xwayland->xwm, cur->pixels, cur->stride, cur->width,
|
2017-11-02 15:49:22 +00:00
|
|
|
cur->height, cur->hotspot_x, cur->hotspot_y);
|
|
|
|
}
|
|
|
|
|
2022-08-18 11:16:16 +00:00
|
|
|
wl_signal_emit_mutable(&xwayland->events.ready, NULL);
|
2018-05-06 18:23:10 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) {
|
|
|
|
if (!xwayland) {
|
2018-09-08 11:00:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
wl_list_remove(&xwayland->server_destroy.link);
|
2022-10-18 11:09:17 +00:00
|
|
|
wl_list_remove(&xwayland->server_start.link);
|
2020-05-05 08:24:08 +00:00
|
|
|
wl_list_remove(&xwayland->server_ready.link);
|
2021-01-17 11:26:10 +00:00
|
|
|
free(xwayland->cursor);
|
2020-05-05 08:24:08 +00:00
|
|
|
|
|
|
|
wlr_xwayland_set_seat(xwayland, NULL);
|
|
|
|
wlr_xwayland_server_destroy(xwayland->server);
|
2022-10-18 11:09:17 +00:00
|
|
|
wlr_xwayland_shell_v1_destroy(xwayland->shell_v1);
|
2020-05-05 08:24:08 +00:00
|
|
|
free(xwayland);
|
2017-08-20 05:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
|
2018-05-06 18:23:10 +00:00
|
|
|
struct wlr_compositor *compositor, bool lazy) {
|
2020-05-05 08:24:08 +00:00
|
|
|
struct wlr_xwayland *xwayland = calloc(1, sizeof(struct wlr_xwayland));
|
|
|
|
if (!xwayland) {
|
2018-05-08 20:22:35 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2018-05-06 18:23:10 +00:00
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
xwayland->wl_display = wl_display;
|
|
|
|
xwayland->compositor = compositor;
|
2018-05-06 18:23:10 +00:00
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
wl_signal_init(&xwayland->events.new_surface);
|
|
|
|
wl_signal_init(&xwayland->events.ready);
|
2021-01-29 15:45:44 +00:00
|
|
|
wl_signal_init(&xwayland->events.remove_startup_info);
|
2017-12-29 19:50:50 +00:00
|
|
|
|
2022-10-18 11:09:17 +00:00
|
|
|
xwayland->shell_v1 = wlr_xwayland_shell_v1_create(wl_display, 1);
|
|
|
|
if (xwayland->shell_v1 == NULL) {
|
|
|
|
free(xwayland);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-05-19 15:28:23 +00:00
|
|
|
struct wlr_xwayland_server_options options = {
|
|
|
|
.lazy = lazy,
|
|
|
|
.enable_wm = true,
|
2022-12-08 01:04:58 +00:00
|
|
|
#if HAVE_XCB_XFIXES_SET_CLIENT_DISCONNECT_MODE
|
2021-06-25 11:49:47 +00:00
|
|
|
.terminate_delay = lazy ? 10 : 0,
|
|
|
|
#endif
|
2020-05-19 15:28:23 +00:00
|
|
|
};
|
|
|
|
xwayland->server = wlr_xwayland_server_create(wl_display, &options);
|
2020-05-05 08:24:08 +00:00
|
|
|
if (xwayland->server == NULL) {
|
2022-10-18 11:09:17 +00:00
|
|
|
wlr_xwayland_shell_v1_destroy(xwayland->shell_v1);
|
2020-06-04 14:23:51 +00:00
|
|
|
free(xwayland);
|
2020-05-05 08:24:08 +00:00
|
|
|
return NULL;
|
2018-05-06 18:23:10 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
xwayland->display_name = xwayland->server->display_name;
|
2018-05-06 18:23:10 +00:00
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
xwayland->server_destroy.notify = handle_server_destroy;
|
|
|
|
wl_signal_add(&xwayland->server->events.destroy, &xwayland->server_destroy);
|
2018-05-06 18:23:10 +00:00
|
|
|
|
2022-10-18 11:09:17 +00:00
|
|
|
xwayland->server_start.notify = handle_server_start;
|
|
|
|
wl_signal_add(&xwayland->server->events.start, &xwayland->server_start);
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
xwayland->server_ready.notify = handle_server_ready;
|
|
|
|
wl_signal_add(&xwayland->server->events.ready, &xwayland->server_ready);
|
2018-05-06 18:23:10 +00:00
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
return xwayland;
|
2017-08-20 05:59:03 +00:00
|
|
|
}
|
2017-11-02 15:49:22 +00:00
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
void wlr_xwayland_set_cursor(struct wlr_xwayland *xwayland,
|
2017-11-02 15:49:22 +00:00
|
|
|
uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height,
|
|
|
|
int32_t hotspot_x, int32_t hotspot_y) {
|
2020-05-05 08:24:08 +00:00
|
|
|
if (xwayland->xwm != NULL) {
|
|
|
|
xwm_set_cursor(xwayland->xwm, pixels, stride, width, height,
|
2017-11-02 15:49:22 +00:00
|
|
|
hotspot_x, hotspot_y);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
free(xwayland->cursor);
|
2017-11-02 15:49:22 +00:00
|
|
|
|
2020-05-05 08:24:08 +00:00
|
|
|
xwayland->cursor = calloc(1, sizeof(struct wlr_xwayland_cursor));
|
|
|
|
if (xwayland->cursor == NULL) {
|
2017-11-02 15:49:22 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-05 08:24:08 +00:00
|
|
|
xwayland->cursor->pixels = pixels;
|
|
|
|
xwayland->cursor->stride = stride;
|
|
|
|
xwayland->cursor->width = width;
|
|
|
|
xwayland->cursor->height = height;
|
|
|
|
xwayland->cursor->hotspot_x = hotspot_x;
|
|
|
|
xwayland->cursor->hotspot_y = hotspot_y;
|
2017-11-02 15:49:22 +00:00
|
|
|
}
|
2017-11-22 13:10:06 +00:00
|
|
|
|
2018-04-25 22:51:00 +00:00
|
|
|
static void xwayland_handle_seat_destroy(struct wl_listener *listener,
|
2017-12-29 16:55:16 +00:00
|
|
|
void *data) {
|
|
|
|
struct wlr_xwayland *xwayland =
|
|
|
|
wl_container_of(listener, xwayland, seat_destroy);
|
|
|
|
|
|
|
|
wlr_xwayland_set_seat(xwayland, NULL);
|
|
|
|
}
|
|
|
|
|
2017-11-22 13:10:06 +00:00
|
|
|
void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland,
|
|
|
|
struct wlr_seat *seat) {
|
2017-12-29 16:55:16 +00:00
|
|
|
if (xwayland->seat) {
|
|
|
|
wl_list_remove(&xwayland->seat_destroy.link);
|
|
|
|
}
|
|
|
|
|
2017-11-22 13:23:23 +00:00
|
|
|
xwayland->seat = seat;
|
|
|
|
|
|
|
|
if (xwayland->xwm) {
|
|
|
|
xwm_set_seat(xwayland->xwm, seat);
|
|
|
|
}
|
2017-12-29 16:55:16 +00:00
|
|
|
|
|
|
|
if (seat == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-25 22:51:00 +00:00
|
|
|
xwayland->seat_destroy.notify = xwayland_handle_seat_destroy;
|
2017-12-29 16:55:16 +00:00
|
|
|
wl_signal_add(&seat->events.destroy, &xwayland->seat_destroy);
|
2017-11-22 13:10:06 +00:00
|
|
|
}
|