From 79c237f323568bbf60b7ae881ef5af5e7d9c3ed7 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Tue, 15 May 2018 19:23:14 -0700 Subject: [PATCH] fileManager1API: Add support for proposed new location mapping mechanism The original xid based window mapping that was implemented for Unity cannot be used Wayland because there are no xids and Wayland has no equivalent window id mechanism. However, GtkApplications do publish window identiy information over dbus, and these 'window object paths' are tracked and made available by mutter. Fortunately for us, Nautilus is a GtkApplication and has identified windows. So, if we update the Nautilus patch to use window object paths instead of xids, we can maintain a mapping that works under Wayland too. This change implements path based tracking alongside xid based tracking, but it's likely we'd drop xid tracking when merging this set of changes. --- fileManager1API.js | 79 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/fileManager1API.js b/fileManager1API.js index 4adc8c19b0..35dacb27d6 100644 --- a/fileManager1API.js +++ b/fileManager1API.js @@ -9,20 +9,25 @@ const Utils = Me.imports.utils; const FileManager1Iface = '\ \ + \ '; const FileManager1Proxy = Gio.DBusProxy.makeProxyWrapper(FileManager1Iface); /** * This class implements a client for the org.freedesktop.FileManager1 dbus - * interface, and specifically for the XUbuntuOpenLocationsXids property that - * is not an official part of the interface. On Ubuntu, Nautilus has been - * patched to offer this additional property, and it maps file locations to - * Window XIDs, as the name suggests. + * interface, and specifically for the OpenWindowsWithLocations property + * which is published by Nautilus, but is not an official part of the interface. * - * When an unpatched Nautilus is running, we will never observe the property - * to contain anything interesting, but there will not be any correctness - * issues. + * The property is a map from window identifiers to a list of locations open in + * the window. + * + * While OpeWindowsWithLocations is part of upstream Nautilus, for many years + * prior, Ubuntu patched Nautilus to publish XUbuntuOpenLocationsXids, which is + * similar but uses Xids as the window identifiers instead of gtk window paths. + * + * When an old or unpatched Nautilus is running, we will observe the properties + * to always be empty arrays, but there will not be any correctness issues. */ var FileManager1Client = new Lang.Class({ Name: 'DashToDock.FileManager1Client', @@ -86,12 +91,52 @@ var FileManager1Client = new Lang.Class({ _onPropertyChanged: function(proxy, changed, invalidated) { let property = changed.unpack(); - if (property && 'XUbuntuOpenLocationsXids' in property) { + if (property && + ('XUbuntuOpenLocationsXids' in property || + 'OpenWindowsWithLocations' in property)) { this._updateLocationMap(); } }, _updateLocationMap: function() { + let properties = this._proxy.get_cached_property_names(); + if (properties == null) { + // Nothing to check yet. + return; + } + + if (properties.includes('OpenWindowsWithLocations')) { + this._updateFromPaths(); + } else if (properties.includes('XUbuntuOpenLocationsXids')) { + this._updateFromXids(); + } + }, + + _updateFromPaths: function() { + let pathToLocations = this._proxy.OpenWindowsWithLocations; + let pathToWindow = getPathToWindow(); + + let locationToWindow = new Map(); + for (let path in pathToLocations) { + let locations = pathToLocations[path]; + for (let i = 0; i < locations.length; i++) { + let l = locations[i]; + // Use a set to deduplicate when a window has a + // location open in multiple tabs. + if (!locationToWindow.has(l)) { + locationToWindow.set(l, new Set()); + } + let window = pathToWindow.get(path); + if (window != null) { + locationToWindow.get(l).add(window); + } + } + } + this._locationMap = locationToWindow; + this.emit('windows-changed'); + }, + + _updateFromXids: function() { let xidToLocations = this._proxy.XUbuntuOpenLocationsXids; let xidToWindow = getXidToWindow(); @@ -117,6 +162,24 @@ var FileManager1Client = new Lang.Class({ }); Signals.addSignalMethods(FileManager1Client.prototype); +/** + * Construct a map of gtk application window object paths to MetaWindows. + */ +function getPathToWindow() { + let pathToWindow = new Map(); + + for (let i = 0; i < global.screen.n_workspaces; i++) { + let ws = global.screen.get_workspace_by_index(i); + ws.list_windows().map(function(w) { + let path = w.get_gtk_window_object_path(); + if (path != null) { + pathToWindow.set(path, w); + } + }); + } + return pathToWindow; +} + /** * Construct a map of XIDs to MetaWindows. *