[mutter] window: Add get_client_pid() method



commit 1fab6e69b74404ef0959f32900637d907dbe1634
Author: Florian Müllner <fmuellner gnome org>
Date:   Fri Oct 7 17:55:32 2016 +0200

    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(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 0f64ace..81f1c31 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 7793dcc..67abbcc 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 60716fb..3fea483 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",
@@ -7056,6 +7063,21 @@ meta_window_get_transient_for (MetaWindow *window)
 }
 
 /**
+ * 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 7dd6f42..b74a8fa 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 3d47f0d..c8b9b04 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -28,6 +28,9 @@
 #include <string.h>
 #include <X11/Xatom.h>
 #include <X11/Xlibint.h> /* For display->resource_mask */
+#include <X11/Xlib-xcb.h>
+
+#include <xcb/res.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
 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]