[gnome-shell/wip/rstrode/rhel-8.0.0: 32/50] introspect: Add GetWindows method



commit 8331a68ae3af42facccc68d45560001feab005b7
Author: Olivier Fourdan <ofourdan redhat com>
Date:   Wed Dec 12 16:02:29 2018 +0100

    introspect: Add GetWindows method
    
    The `GetWindows` method gives access to the list of windows for each
    application with some of their properties, so utilities such as dogtail
    can pick the window of their choice to interfere with using the provided
    window id.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/326
    (cherry picked from commit 0f45b438e2b956d3cf52622db875dedab45e49b9)

 data/org.gnome.Shell.Introspect.xml | 24 +++++++++++++++
 js/misc/introspect.js               | 58 +++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)
---
diff --git a/data/org.gnome.Shell.Introspect.xml b/data/org.gnome.Shell.Introspect.xml
index 10c48d635..9508681af 100644
--- a/data/org.gnome.Shell.Introspect.xml
+++ b/data/org.gnome.Shell.Introspect.xml
@@ -33,5 +33,29 @@
     <method name="GetRunningApplications">
       <arg name="apps" direction="out" type="a{sa{sv}}" />
     </method>
+
+    <!--
+        GetWindows:
+        @short_description: Retrieves the current list of windows and their properties
+
+        A window is exposed as:
+        * t ID: unique ID of the window
+        * a{sv} properties: high-level properties
+
+          Known properties:
+
+          - "title"       (s): (readonly) title of the window
+          - "app-id"      (s): (readonly) application ID of the window
+          - "wm-class"    (s): (readonly) class of the window
+          - "client-type" (u): (readonly) 0 for Wayland, 1 for X11
+          - "is-hidden"   (b): (readonly) if the window is currently hidden
+          - "has-focus"   (b): (readonly) if the window currently have
+                                          keyboard focus
+          - "width"       (u): (readonly) width of the window
+          - "height"      (u): (readonly) height of the window
+    -->
+    <method name="GetWindows">
+      <arg name="windows" direction="out" type="a{ta{sv}}" />
+    </method>
   </interface>
 </node>
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index 05ef9e637..5999fc1f0 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -14,6 +14,9 @@ const IntrospectDBusIface = '<node> \
     <method name="GetRunningApplications"> \
       <arg name="apps" direction="out" type="a{sa{sv}}" /> \
     </method> \
+    <method name="GetWindows"> \
+      <arg name="windows" direction="out" type="a{ta{sv}}" /> \
+    </method> \
   </interface> \
 </node>';
 
@@ -102,6 +105,17 @@ var IntrospectService = new Lang.Class({
         this._activeApplicationDirty = false;
     },
 
+    _isEligibleWindow(window) {
+        if (window.is_override_redirect())
+            return false;
+
+        let type = window.get_window_type();
+        return (type == Meta.WindowType.NORMAL ||
+                type == Meta.WindowType.DIALOG ||
+                type == Meta.WindowType.MODAL_DIALOG ||
+                type == Meta.WindowType.UTILITY);
+    },
+
     GetRunningApplicationsAsync(params, invocation) {
         if (!this._isIntrospectEnabled() &&
             !this._isSenderWhitelisted(invocation.get_sender())) {
@@ -112,5 +126,49 @@ var IntrospectService = new Lang.Class({
         }
 
         invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications]));
+    },
+
+    GetWindowsAsync(params, invocation) {
+        let focusWindow = global.display.get_focus_window();
+        let apps = this._appSystem.get_running();
+        let windowsList = {};
+
+        if (!this._isIntrospectEnabled()) {
+            invocation.return_error_literal(Gio.DBusError,
+                                            Gio.DBusError.ACCESS_DENIED,
+                                            'App introspection not allowed');
+            return;
+        }
+
+        for (let app of apps) {
+            let windows = app.get_windows();
+            for (let window of windows) {
+
+                if (!this._isEligibleWindow(window))
+                    continue;
+
+                let windowId = window.get_id();
+                let frameRect = window.get_frame_rect();
+                let title = window.get_title();
+                let wmClass = window.get_wm_class();
+
+                windowsList[windowId] = {
+                    'app-id': GLib.Variant.new('s', app.get_id()),
+                    'client-type': GLib.Variant.new('u', window.get_client_type()),
+                    'is-hidden': GLib.Variant.new('b', window.is_hidden()),
+                    'has-focus': GLib.Variant.new('b', (window == focusWindow)),
+                    'width': GLib.Variant.new('u', frameRect.width),
+                    'height': GLib.Variant.new('u', frameRect.height)
+                };
+
+                // These properties may not be available for all windows:
+                if (title != null)
+                    windowsList[windowId]['title'] = GLib.Variant.new('s', title);
+
+                if (wmClass != null)
+                    windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass);
+            }
+        }
+        invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
     }
 });


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