Skip to content

Commit

Permalink
fileManager1API: Add support for proposed new location mapping mechanism
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
philipl committed May 19, 2018
1 parent 1705129 commit 79c237f
Showing 1 changed file with 71 additions and 8 deletions.
79 changes: 71 additions & 8 deletions fileManager1API.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,25 @@ const Utils = Me.imports.utils;

const FileManager1Iface = '<node><interface name="org.freedesktop.FileManager1">\
<property name="XUbuntuOpenLocationsXids" type="a{uas}" access="read"/>\
<property name="OpenWindowsWithLocations" type="a{sas}" access="read"/>\
</interface></node>';

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',
Expand Down Expand Up @@ -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();

Expand All @@ -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.
*
Expand Down

0 comments on commit 79c237f

Please sign in to comment.