Merge branch 'wip/corey/tracked-windows' into 'main'

introspect: Pass a window with the WindowsChanged signal

See merge request GNOME/gnome-shell!2895
This commit is contained in:
Corey Berla 2024-06-29 14:21:01 +00:00
commit fb45998c3f
4 changed files with 90 additions and 35 deletions

View file

@ -19,11 +19,26 @@
<signal name="RunningApplicationsChanged" />
<!--
WindowsChanged:
@short_description: Notifies when any window opens or closes
WindowAdded:
@short_description: Notifies when any window opens
-->
<signal name="WindowsChanged" />
<signal name="WindowAdded">
<arg type="a{sv}" name="window" />
</signal>
<!--
WindowChanged:
@short_description: Notifies when any window changes
-->
<signal name="WindowChanged">
<arg type="a{sv}" name="window" />
</signal>
<!--
WindowRemoved:
@short_description: Notifies when any window closes
-->
<signal name="WindowRemoved">
<arg type="a{sv}" name="window" />
</signal>
<!--
GetRunningApplications:
@short_description: Retrieves the description of all running applications

View file

@ -44,7 +44,25 @@ export class IntrospectService {
});
tracker.connect('tracked-windows-changed',
() => this._dbusImpl.emit_signal('WindowsChanged', null));
(self, window, app, action) => {
if (!this._isEligibleWindow(window))
return;
let windowDict = this._getWindowDict(window, app);
let windowVariant = new GLib.Variant('(a{sv})', [windowDict]);
switch (action) {
case Shell.WindowTrackerAction.ADDED:
this._dbusImpl.emit_signal('WindowAdded', windowVariant);
break;
case Shell.WindowTrackerAction.CHANGED:
this._dbusImpl.emit_signal('WindowChanged', windowVariant);
break;
case Shell.WindowTrackerAction.REMOVED:
this._dbusImpl.emit_signal('WindowRemoved', windowVariant);
break;
default:
log(`Incorrect window action ${action}`);
}
});
this._syncRunningApplications();
@ -121,6 +139,38 @@ export class IntrospectService {
type === Meta.WindowType.UTILITY;
}
_getWindowDict(window, app) {
let focusWindow = global.display.get_focus_window();
let windowId = window.get_id();
let frameRect = window.get_frame_rect();
let title = window.get_title();
let wmClass = window.get_wm_class();
let sandboxedAppId = window.get_sandboxed_app_id();
let windowDict = {
'app-id': GLib.Variant.new('s', app.get_id()),
'client-type': GLib.Variant.new('u', window.get_client_type()),
'id': GLib.Variant.new('t', windowId),
'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)
windowDict['title'] = GLib.Variant.new('s', title);
if (wmClass != null)
windowDict['wm-class'] = GLib.Variant.new('s', wmClass);
if (sandboxedAppId != null) {
windowDict['sandboxed-app-id'] =
GLib.Variant.new('s', sandboxedAppId);
}
return windowDict;
}
async GetRunningApplicationsAsync(params, invocation) {
try {
await this._senderChecker.checkInvocation(invocation);
@ -133,7 +183,6 @@ export class IntrospectService {
}
async GetWindowsAsync(params, invocation) {
let focusWindow = global.display.get_focus_window();
let apps = this._appSystem.get_running();
let windowsList = {};
@ -151,31 +200,8 @@ export class IntrospectService {
continue;
let windowId = window.get_id();
let frameRect = window.get_frame_rect();
let title = window.get_title();
let wmClass = window.get_wm_class();
let sandboxedAppId = window.get_sandboxed_app_id();
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);
if (sandboxedAppId != null) {
windowsList[windowId]['sandboxed-app-id'] =
GLib.Variant.new('s', sandboxedAppId);
}
let windowDict = this._getWindowVariant(window, app);
windowsList[windowId] = new GLib.Variant('a{sv}', windowDict);
}
}
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));

View file

@ -124,7 +124,9 @@ shell_window_tracker_class_init (ShellWindowTrackerClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
G_TYPE_NONE,
3, META_TYPE_WINDOW, SHELL_TYPE_APP,
G_TYPE_INT);
}
static gboolean
@ -533,8 +535,12 @@ on_title_changed (MetaWindow *window,
GParamSpec *pspec,
gpointer user_data)
{
ShellApp *app;
ShellWindowTracker *self = SHELL_WINDOW_TRACKER (user_data);
g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0);
app = get_app_for_window (self, window);
g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0, window, app, SHELL_WINDOW_TRACKER_CHANGED);
}
static void
@ -573,7 +579,7 @@ track_window (ShellWindowTracker *self,
_shell_app_add_window (app, window);
g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0);
g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0, window, app, SHELL_WINDOW_TRACKER_ADDED);
}
static void
@ -594,6 +600,7 @@ disassociate_window (ShellWindowTracker *self,
if (!app)
return;
g_object_ref (window);
g_object_ref (app);
g_hash_table_remove (self->window_to_app, window);
@ -604,8 +611,9 @@ disassociate_window (ShellWindowTracker *self,
g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_gtk_application_id_changed), self);
g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_window_unmanaged), self);
g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0);
g_signal_emit (self, signals[TRACKED_WINDOWS_CHANGED], 0, window, app, SHELL_WINDOW_TRACKER_REMOVED);
g_object_unref (window);
g_object_unref (app);
}

View file

@ -16,6 +16,12 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (ShellWindowTracker, shell_window_tracker,
SHELL, WINDOW_TRACKER, GObject)
typedef enum {
SHELL_WINDOW_TRACKER_ADDED,
SHELL_WINDOW_TRACKER_CHANGED,
SHELL_WINDOW_TRACKER_REMOVED
} ShellWindowTrackerAction;
ShellWindowTracker* shell_window_tracker_get_default(void);
ShellApp *shell_window_tracker_get_window_app (ShellWindowTracker *tracker, MetaWindow *metawin);