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
This commit is contained in:
Florian Müllner 2016-10-07 17:55:32 +02:00
parent f89162ee73
commit 1fab6e69b7
5 changed files with 78 additions and 0 deletions

View File

@ -85,6 +85,7 @@ MUTTER_PC_MODULES="
xrender xrender
x11-xcb x11-xcb
xcb-randr xcb-randr
xcb-res
" "
GLIB_GSETTINGS GLIB_GSETTINGS

View File

@ -524,6 +524,7 @@ struct _MetaWindowClass
gboolean (*update_icon) (MetaWindow *window, gboolean (*update_icon) (MetaWindow *window,
cairo_surface_t **icon, cairo_surface_t **icon,
cairo_surface_t **mini_icon); cairo_surface_t **mini_icon);
uint32_t (*get_client_pid) (MetaWindow *window);
void (*update_main_monitor) (MetaWindow *window); void (*update_main_monitor) (MetaWindow *window);
void (*main_monitor_changed) (MetaWindow *window, void (*main_monitor_changed) (MetaWindow *window,
const MetaMonitorInfo *old); const MetaMonitorInfo *old);
@ -705,6 +706,8 @@ void meta_window_handle_leave (MetaWindow *window);
void meta_window_handle_ungrabbed_event (MetaWindow *window, void meta_window_handle_ungrabbed_event (MetaWindow *window,
const ClutterEvent *event); const ClutterEvent *event);
uint32_t meta_window_get_client_pid (MetaWindow *window);
void meta_window_get_client_area_rect (const MetaWindow *window, void meta_window_get_client_area_rect (const MetaWindow *window,
cairo_rectangle_int_t *rect); cairo_rectangle_int_t *rect);
void meta_window_get_titlebar_rect (MetaWindow *window, void meta_window_get_titlebar_rect (MetaWindow *window,

View File

@ -253,6 +253,12 @@ meta_window_real_update_icon (MetaWindow *window,
return FALSE; return FALSE;
} }
static uint32_t
meta_window_real_get_client_pid (MetaWindow *window)
{
return 0;
}
static void static void
meta_window_finalize (GObject *object) meta_window_finalize (GObject *object)
{ {
@ -420,6 +426,7 @@ meta_window_class_init (MetaWindowClass *klass)
klass->update_struts = meta_window_real_update_struts; klass->update_struts = meta_window_real_update_struts;
klass->get_default_skip_hints = meta_window_real_get_default_skip_hints; klass->get_default_skip_hints = meta_window_real_get_default_skip_hints;
klass->update_icon = meta_window_real_update_icon; klass->update_icon = meta_window_real_update_icon;
klass->get_client_pid = meta_window_real_get_client_pid;
obj_props[PROP_TITLE] = obj_props[PROP_TITLE] =
g_param_spec_string ("title", g_param_spec_string ("title",
@ -7055,6 +7062,21 @@ meta_window_get_transient_for (MetaWindow *window)
return NULL; 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: * meta_window_get_pid:
* @window: a #MetaWindow * @window: a #MetaWindow

View File

@ -453,6 +453,17 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
meta_window_emit_size_changed (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 static void
appears_focused_changed (GObject *object, appears_focused_changed (GObject *object,
GParamSpec *pspec, 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->move_resize_internal = meta_window_wayland_move_resize_internal;
window_class->update_main_monitor = meta_window_wayland_update_main_monitor; window_class->update_main_monitor = meta_window_wayland_update_main_monitor;
window_class->main_monitor_changed = meta_window_wayland_main_monitor_changed; window_class->main_monitor_changed = meta_window_wayland_main_monitor_changed;
window_class->get_client_pid = meta_window_wayland_get_client_pid;
} }
MetaWindow * MetaWindow *

View File

@ -28,6 +28,9 @@
#include <string.h> #include <string.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xlibint.h> /* For display->resource_mask */ #include <X11/Xlibint.h> /* For display->resource_mask */
#include <X11/Xlib-xcb.h>
#include <xcb/res.h>
#include <X11/extensions/shape.h> #include <X11/extensions/shape.h>
@ -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 static void
meta_window_x11_class_init (MetaWindowX11Class *klass) 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_icon = meta_window_x11_update_icon;
window_class->update_main_monitor = meta_window_x11_update_main_monitor; window_class->update_main_monitor = meta_window_x11_update_main_monitor;
window_class->main_monitor_changed = meta_window_x11_main_monitor_changed; window_class->main_monitor_changed = meta_window_x11_main_monitor_changed;
window_class->get_client_pid = meta_window_x11_get_client_pid;
} }
void void