aboutsummaryrefslogtreecommitdiff
path: root/xwayland
diff options
context:
space:
mode:
authorAleksei Bavshin <alebastr89@gmail.com>2021-04-16 19:27:12 -0700
committerSimon Ser <contact@emersion.fr>2021-04-23 09:55:01 +0200
commite0f239fa2828318e9eff6b68f7faafecd338914c (patch)
treeb871ac9fffed0a3aebe3a2c73a9aa389675db1d4 /xwayland
parentc314920a3d2bcb347d9ae491a678d8349f32ae8d (diff)
xwayland: query window PIDs via XResQueryClientIds
`_NET_WM_PID` is unreliable: it is optional and even if set it may contain PIDs from sandbox namespaces or remote systems. Prefer XRes v1.2 QueryClientIds method which returns PIDs as seen by the Xwayland server.
Diffstat (limited to 'xwayland')
-rw-r--r--xwayland/meson.build1
-rw-r--r--xwayland/xwm.c63
2 files changed, 64 insertions, 0 deletions
diff --git a/xwayland/meson.build b/xwayland/meson.build
index bbf96eac..b7bbcaf1 100644
--- a/xwayland/meson.build
+++ b/xwayland/meson.build
@@ -4,6 +4,7 @@ xwayland_required = [
'xcb-composite',
'xcb-icccm',
'xcb-render',
+ 'xcb-res',
'xcb-xfixes',
]
xwayland_optional = {
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index f380f8f1..9ac2773d 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -14,6 +14,7 @@
#include <wlr/xwayland.h>
#include <xcb/composite.h>
#include <xcb/render.h>
+#include <xcb/res.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xfixes.h>
#include "util/signal.h"
@@ -510,6 +511,41 @@ static void read_surface_parent(struct wlr_xwm *xwm,
wlr_signal_emit_safe(&xsurface->events.set_parent, xsurface);
}
+static void read_surface_client_id(struct wlr_xwm *xwm,
+ struct wlr_xwayland_surface *xsurface) {
+ xcb_res_client_id_spec_t spec = {
+ .client = xsurface->window_id,
+ .mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID
+ };
+
+ xcb_res_query_client_ids_cookie_t cookie = xcb_res_query_client_ids(
+ xwm->xcb_conn, 1, &spec);
+ xcb_res_query_client_ids_reply_t *reply = xcb_res_query_client_ids_reply(
+ xwm->xcb_conn, cookie, NULL);
+ if (reply == NULL) {
+ return;
+ }
+
+ uint32_t *pid = NULL;
+ xcb_res_client_id_value_iterator_t iter =
+ xcb_res_query_client_ids_ids_iterator(reply);
+ while (iter.rem > 0) {
+ if (iter.data->spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID &&
+ xcb_res_client_id_value_value_length(iter.data) > 0) {
+ pid = xcb_res_client_id_value_value(iter.data);
+ break;
+ }
+ xcb_res_client_id_value_next(&iter);
+ }
+ if (pid == NULL) {
+ free(reply);
+ return;
+ }
+ xsurface->pid = *pid;
+ wlr_signal_emit_safe(&xsurface->events.set_pid, xsurface);
+ free(reply);
+}
+
static void read_surface_pid(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) {
@@ -818,6 +854,9 @@ static void xwm_map_shell_surface(struct wlr_xwm *xwm,
for (size_t i = 0; i < sizeof(props)/sizeof(xcb_atom_t); i++) {
read_surface_property(xwm, xsurface, props[i]);
}
+ if (xwm->xres) {
+ read_surface_client_id(xwm, xsurface);
+ }
xsurface->surface_destroy.notify = handle_surface_destroy;
wl_signal_add(&surface->events.destroy, &xsurface->surface_destroy);
@@ -1621,6 +1660,7 @@ void xwm_destroy(struct wlr_xwm *xwm) {
static void xwm_get_resources(struct wlr_xwm *xwm) {
xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_xfixes_id);
xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_composite_id);
+ xcb_prefetch_extension_data(xwm->xcb_conn, &xcb_res_id);
size_t i;
xcb_intern_atom_cookie_t cookies[ATOM_LAST];
@@ -1664,6 +1704,29 @@ static void xwm_get_resources(struct wlr_xwm *xwm) {
xfixes_reply->major_version, xfixes_reply->minor_version);
free(xfixes_reply);
+
+ const xcb_query_extension_reply_t *xres =
+ xcb_get_extension_data(xwm->xcb_conn, &xcb_res_id);
+ if (!xres || !xres->present) {
+ return;
+ }
+
+ xcb_res_query_version_cookie_t xres_cookie =
+ xcb_res_query_version(xwm->xcb_conn, XCB_RES_MAJOR_VERSION,
+ XCB_RES_MINOR_VERSION);
+ xcb_res_query_version_reply_t *xres_reply =
+ xcb_res_query_version_reply(xwm->xcb_conn, xres_cookie, NULL);
+ if (xres_reply == NULL) {
+ return;
+ }
+
+ wlr_log(WLR_DEBUG, "xres version: %" PRIu32 ".%" PRIu32,
+ xres_reply->server_major, xres_reply->server_minor);
+ if (xres_reply->server_major > 1 ||
+ (xres_reply->server_major == 1 && xres_reply->server_minor >= 2)) {
+ xwm->xres = xres;
+ }
+ free(xres_reply);
}
static void xwm_create_wm_window(struct wlr_xwm *xwm) {