From 1fab6e69b74404ef0959f32900637d907dbe1634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 7 Oct 2016 17:55:32 +0200 Subject: [PATCH] window: Add get_client_pid() method It is often useful to identify the client process that created a particular window, however the existing meta_window_get_pid() method relies on _NET_WM_PID, which is only available on X11 and depends on applications to set it correctly (which may not even be possible when the app runs in its own PID namespace as Flatpak apps do). So add a get_client_pid() method that uses windowing system facilities to resolve the PID associated with a particular window. https://bugzilla.gnome.org/show_bug.cgi?id=772613 --- configure.ac | 1 + src/core/window-private.h | 3 +++ src/core/window.c | 22 +++++++++++++++++ src/wayland/meta-window-wayland.c | 12 ++++++++++ src/x11/window-x11.c | 40 +++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+) diff --git a/configure.ac b/configure.ac index 0f64aceba..81f1c3144 100644 --- a/configure.ac +++ b/configure.ac @@ -85,6 +85,7 @@ MUTTER_PC_MODULES=" xrender x11-xcb xcb-randr + xcb-res " GLIB_GSETTINGS diff --git a/src/core/window-private.h b/src/core/window-private.h index 7793dccb9..67abbccd8 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -524,6 +524,7 @@ struct _MetaWindowClass gboolean (*update_icon) (MetaWindow *window, cairo_surface_t **icon, cairo_surface_t **mini_icon); + uint32_t (*get_client_pid) (MetaWindow *window); void (*update_main_monitor) (MetaWindow *window); void (*main_monitor_changed) (MetaWindow *window, const MetaMonitorInfo *old); @@ -705,6 +706,8 @@ void meta_window_handle_leave (MetaWindow *window); void meta_window_handle_ungrabbed_event (MetaWindow *window, const ClutterEvent *event); +uint32_t meta_window_get_client_pid (MetaWindow *window); + void meta_window_get_client_area_rect (const MetaWindow *window, cairo_rectangle_int_t *rect); void meta_window_get_titlebar_rect (MetaWindow *window, diff --git a/src/core/window.c b/src/core/window.c index 60716fb56..3fea48353 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -253,6 +253,12 @@ meta_window_real_update_icon (MetaWindow *window, return FALSE; } +static uint32_t +meta_window_real_get_client_pid (MetaWindow *window) +{ + return 0; +} + static void meta_window_finalize (GObject *object) { @@ -420,6 +426,7 @@ meta_window_class_init (MetaWindowClass *klass) klass->update_struts = meta_window_real_update_struts; klass->get_default_skip_hints = meta_window_real_get_default_skip_hints; klass->update_icon = meta_window_real_update_icon; + klass->get_client_pid = meta_window_real_get_client_pid; obj_props[PROP_TITLE] = g_param_spec_string ("title", @@ -7055,6 +7062,21 @@ meta_window_get_transient_for (MetaWindow *window) return NULL; } +/** + * meta_window_get_client_pid: + * @window: a #MetaWindow + * + * Returns the pid of the process that created this window, if available + * to the windowing system. + * + * Return value: the pid, or 0 if not known. + */ +uint32_t +meta_window_get_client_pid (MetaWindow *window) +{ + return META_WINDOW_GET_CLASS (window)->get_client_pid (window); +} + /** * meta_window_get_pid: * @window: a #MetaWindow diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 7dd6f4247..b74a8fac6 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -453,6 +453,17 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window, meta_window_emit_size_changed (window); } +static uint32_t +meta_window_wayland_get_client_pid (MetaWindow *window) +{ + MetaWaylandSurface *surface = window->surface; + struct wl_resource *resource = surface->resource; + pid_t pid; + + wl_client_get_credentials (wl_resource_get_client (resource), &pid, NULL, NULL); + return (uint32_t)pid; +} + static void appears_focused_changed (GObject *object, GParamSpec *pspec, @@ -487,6 +498,7 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass) window_class->move_resize_internal = meta_window_wayland_move_resize_internal; window_class->update_main_monitor = meta_window_wayland_update_main_monitor; window_class->main_monitor_changed = meta_window_wayland_main_monitor_changed; + window_class->get_client_pid = meta_window_wayland_get_client_pid; } MetaWindow * diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index 3d47f0d4e..c8b9b0426 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -28,6 +28,9 @@ #include #include #include /* For display->resource_mask */ +#include + +#include #include @@ -1481,6 +1484,42 @@ meta_window_x11_main_monitor_changed (MetaWindow *window, { } +static uint32_t +meta_window_x11_get_client_pid (MetaWindow *window) +{ + xcb_connection_t *xcb = XGetXCBConnection (window->display->xdisplay); + xcb_res_client_id_spec_t spec = { 0 }; + xcb_res_query_client_ids_cookie_t cookie; + xcb_res_query_client_ids_reply_t *reply = NULL; + + spec.client = window->xwindow; + spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; + + cookie = xcb_res_query_client_ids (xcb, 1, &spec); + reply = xcb_res_query_client_ids_reply (xcb, cookie, NULL); + + if (reply == NULL) + return 0; + + uint32_t pid = 0, *value; + xcb_res_client_id_value_iterator_t it; + for (it = xcb_res_query_client_ids_ids_iterator (reply); + it.rem; + xcb_res_client_id_value_next (&it)) + { + spec = it.data->spec; + if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) + { + value = xcb_res_client_id_value_value (it.data); + pid = *value; + break; + } + } + + free (reply); + return pid; +} + static void meta_window_x11_class_init (MetaWindowX11Class *klass) { @@ -1501,6 +1540,7 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) window_class->update_icon = meta_window_x11_update_icon; window_class->update_main_monitor = meta_window_x11_update_main_monitor; window_class->main_monitor_changed = meta_window_x11_main_monitor_changed; + window_class->get_client_pid = meta_window_x11_get_client_pid; } void