aboutsummaryrefslogtreecommitdiff
path: root/xwayland
diff options
context:
space:
mode:
Diffstat (limited to 'xwayland')
-rw-r--r--xwayland/xwayland.c22
-rw-r--r--xwayland/xwm.c27
2 files changed, 46 insertions, 3 deletions
diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c
index 1068b942..4755608f 100644
--- a/xwayland/xwayland.c
+++ b/xwayland/xwayland.c
@@ -74,6 +74,7 @@ static int fill_arg(char ***argv, const char *fmt, ...) {
return len;
}
+_Noreturn
static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
if (unset_cloexec(wlr_xwayland->x_fd[0]) ||
unset_cloexec(wlr_xwayland->x_fd[1]) ||
@@ -123,9 +124,26 @@ static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
wlr_xwayland->wl_fd[1], wlr_xwayland->display, wlr_xwayland->x_fd[0],
wlr_xwayland->x_fd[1], wlr_xwayland->wm_fd[1]);
- // TODO: close stdout/err depending on log level
+ // Closes stdout/stderr depending on log verbosity
+ enum wlr_log_importance verbosity = wlr_log_get_verbosity();
+ int devnull = open("/dev/null", O_WRONLY | O_CREAT, 0666);
+ if (devnull < 0) {
+ wlr_log_errno(WLR_ERROR, "XWayland: failed to open /dev/null");
+ _exit(EXIT_FAILURE);
+ }
+ if (verbosity < WLR_INFO) {
+ dup2(devnull, STDOUT_FILENO);
+ }
+ if (verbosity < WLR_ERROR) {
+ dup2(devnull, STDERR_FILENO);
+ }
+ // This returns if and only if the call fails
execvp("Xwayland", argv);
+
+ wlr_log_errno(WLR_ERROR, "failed to exec Xwayland");
+ close(devnull);
+ _exit(EXIT_FAILURE);
}
static void xwayland_finish_server(struct wlr_xwayland *wlr_xwayland) {
@@ -346,8 +364,6 @@ static bool xwayland_start_server(struct wlr_xwayland *wlr_xwayland) {
sigprocmask(SIG_BLOCK, &sigset, NULL);
if ((pid = fork()) == 0) {
exec_xwayland(wlr_xwayland);
- wlr_log_errno(WLR_ERROR, "failed to exec Xwayland");
- _exit(EXIT_FAILURE);
}
if (pid < 0) {
wlr_log_errno(WLR_ERROR, "second fork failed");
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index cebd9bbc..9c803543 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -24,6 +24,7 @@ const char *atom_map[ATOM_LAST] = {
"WM_HINTS",
"WM_NORMAL_HINTS",
"WM_SIZE_HINTS",
+ "WM_WINDOW_ROLE",
"_MOTIF_WM_HINTS",
"UTF8_STRING",
"WM_S0",
@@ -152,6 +153,7 @@ static struct wlr_xwayland_surface *xwayland_surface_create(
wl_signal_init(&surface->events.map);
wl_signal_init(&surface->events.unmap);
wl_signal_init(&surface->events.set_class);
+ wl_signal_init(&surface->events.set_role);
wl_signal_init(&surface->events.set_title);
wl_signal_init(&surface->events.set_parent);
wl_signal_init(&surface->events.set_pid);
@@ -327,6 +329,7 @@ static void xwayland_surface_destroy(
free(xsurface->title);
free(xsurface->class);
free(xsurface->instance);
+ free(xsurface->role);
free(xsurface->window_type);
free(xsurface->protocols);
free(xsurface->hints);
@@ -365,6 +368,28 @@ static void read_surface_class(struct wlr_xwm *xwm,
wlr_signal_emit_safe(&surface->events.set_class, surface);
}
+static void read_surface_role(struct wlr_xwm *xwm,
+ struct wlr_xwayland_surface *xsurface,
+ xcb_get_property_reply_t *reply) {
+ if (reply->type != XCB_ATOM_STRING &&
+ reply->type != xwm->atoms[UTF8_STRING]) {
+ return;
+ }
+
+ size_t len = xcb_get_property_value_length(reply);
+ char *role = xcb_get_property_value(reply);
+
+ free(xsurface->role);
+ if (len > 0) {
+ xsurface->role = strndup(role, len);
+ } else {
+ xsurface->role = NULL;
+ }
+
+ wlr_log(WLR_DEBUG, "XCB_ATOM_WM_WINDOW_ROLE: %s", xsurface->role);
+ wlr_signal_emit_safe(&xsurface->events.set_role, xsurface);
+}
+
static void read_surface_title(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) {
@@ -638,6 +663,8 @@ static void read_surface_property(struct wlr_xwm *xwm,
read_surface_normal_hints(xwm, xsurface, reply);
} else if (property == xwm->atoms[MOTIF_WM_HINTS]) {
read_surface_motif_hints(xwm, xsurface, reply);
+ } else if (property == xwm->atoms[WM_WINDOW_ROLE]) {
+ read_surface_role(xwm, xsurface, reply);
} else {
char *prop_name = xwm_get_atom_name(xwm, property);
wlr_log(WLR_DEBUG, "unhandled X11 property %u (%s) for window %u",