Skip to content

Commit 8cd67e3

Browse files
committed
autorun: Use a dialog, not a notification.
- Improve the Dialog list widgets to allow selection, proper pseudo-classes for highlighting. - Use existing login manager for lock/unlock listeners (and make our screensaver set the locked hint finally).
1 parent eceff8d commit 8cd67e3

7 files changed

Lines changed: 419 additions & 180 deletions

File tree

data/theme/cinnamon-sass/widgets/_dialogs.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@
4343

4444
.dialog-list-item {
4545
spacing: 1em;
46+
border-radius: $base_border_radius;
47+
padding: $base_padding $base_padding * 2;
48+
transition-duration: 100ms;
49+
50+
&:hover { background-color: $light_bg_color; }
51+
&:selected { background-color: $accent_bg_color; }
4652

4753
.dialog-list-item-title { font-weight: bold; }
4854
.dialog-list-item-description {

js/misc/loginManager.js

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ const SystemdLoginSessionIface = `
3838
<signal name="Lock"/>
3939
<signal name="Unlock"/>
4040
<property name="Active" type="b" access="read"/>
41+
<method name="SetLockedHint">
42+
<arg type="b" direction="in"/>
43+
</method>
4144
</interface>
4245
</node>`;
4346

@@ -75,6 +78,8 @@ var LoginManagerSystemd = class {
7578
constructor() {
7679
this._managerProxy = null;
7780
this._sessionProxy = null;
81+
this.sessionIsActive = true;
82+
this.isLocked = false;
7883

7984
this._initSession();
8085
}
@@ -146,25 +151,26 @@ var LoginManagerSystemd = class {
146151

147152
this._sessionProxy.connectSignal('Lock', () => {
148153
_log('LoginManager: Received Lock signal from logind, emitting lock');
154+
this.isLocked = true;
149155
this.emit('lock');
150156
});
151157

152158
this._sessionProxy.connectSignal('Unlock', () => {
153159
_log('LoginManager: Received Unlock signal from logind, emitting unlock');
160+
this.isLocked = false;
154161
this.emit('unlock');
155162
});
156163

157164
this._sessionProxy.connect('g-properties-changed', (proxy, changed, invalidated) => {
158165
if ('Active' in changed.deep_unpack()) {
159166
let active = this._sessionProxy.Active;
167+
this.sessionIsActive = active;
160168
_log(`LoginManager: Session Active property changed: ${active}`);
161-
if (active) {
162-
_log('LoginManager: Session became active, emitting active');
163-
this.emit('active');
164-
}
169+
this.emit('active-changed', active);
165170
}
166171
});
167172

173+
this.sessionIsActive = this._sessionProxy.Active;
168174
this.emit('session-ready');
169175
} catch (e) {
170176
global.logError('LoginManager: Failed to connect to logind session: ' + e.message);
@@ -208,13 +214,25 @@ var LoginManagerSystemd = class {
208214
}
209215
});
210216
}
217+
218+
setLockedHint(locked) {
219+
if (!this._sessionProxy)
220+
return;
221+
222+
this._sessionProxy.SetLockedHintRemote(locked, (result, error) => {
223+
if (error)
224+
global.logError('LoginManager: SetLockedHint failed: ' + error);
225+
});
226+
}
211227
};
212228
Signals.addSignalMethods(LoginManagerSystemd.prototype);
213229

214230
var LoginManagerConsoleKit = class {
215231
constructor() {
216232
this._managerProxy = null;
217233
this._sessionProxy = null;
234+
this.sessionIsActive = true;
235+
this.isLocked = false;
218236

219237
this._initSession();
220238
}
@@ -259,20 +277,20 @@ var LoginManagerConsoleKit = class {
259277

260278
this._sessionProxy.connectSignal('Lock', () => {
261279
_log('LoginManager: Received Lock signal from ConsoleKit, emitting lock');
280+
this.isLocked = true;
262281
this.emit('lock');
263282
});
264283

265284
this._sessionProxy.connectSignal('Unlock', () => {
266285
_log('LoginManager: Received Unlock signal from ConsoleKit, emitting unlock');
286+
this.isLocked = false;
267287
this.emit('unlock');
268288
});
269289

270290
this._sessionProxy.connectSignal('ActiveChanged', (proxy, sender, [active]) => {
291+
this.sessionIsActive = active;
271292
_log(`LoginManager: ConsoleKit ActiveChanged: ${active}`);
272-
if (active) {
273-
_log('LoginManager: Session became active, emitting active');
274-
this.emit('active');
275-
}
293+
this.emit('active-changed', active);
276294
});
277295

278296
this.emit('session-ready');
@@ -291,6 +309,10 @@ var LoginManagerConsoleKit = class {
291309
// ConsoleKit doesn't have inhibitors
292310
callback(null);
293311
}
312+
313+
setLockedHint(_locked) {
314+
// ConsoleKit doesn't have SetLockedHint
315+
}
294316
};
295317
Signals.addSignalMethods(LoginManagerConsoleKit.prototype);
296318

js/ui/automountManager.js

Lines changed: 41 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
const { Gio, GLib } = imports.gi;
55
const Params = imports.misc.params;
66

7-
const GnomeSession = imports.misc.gnomeSession;
7+
const LoginManager = imports.misc.loginManager;
88
const Main = imports.ui.main;
99
const CinnamonMountOperation = imports.ui.cinnamonMountOperation;
1010

11-
var GNOME_SESSION_AUTOMOUNT_INHIBIT = 16;
12-
1311
// GSettings keys
1412
const SETTINGS_SCHEMA = 'org.cinnamon.desktop.media-handling';
1513
const SETTING_ENABLE_AUTOMOUNT = 'automount';
@@ -20,28 +18,16 @@ var AutomountManager = class {
2018
constructor() {
2119
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
2220
this._activeOperations = new Map();
23-
24-
GnomeSession.SessionManager((proxy, error) => {
25-
if (error)
26-
return;
27-
28-
this._session = proxy;
29-
this.actor.show();
30-
this.updateStatus();
31-
32-
this._session.connectSignal(
33-
"InhibitorAdded",
34-
this._InhibitorsChanged.bind(this)
35-
);
36-
37-
this._session.connectSignal(
38-
"InhibitorRemoved",
39-
this._InhibitorsChanged.bind(this)
40-
);
21+
this._volumeQueue = [];
22+
23+
this._loginManager = LoginManager.getLoginManager();
24+
this._loginManager.connect('lock', () => this._onScreenLocked());
25+
this._loginManager.connect('unlock', () => this._onScreenUnlocked());
26+
this._loginManager.connect('active-changed', (lm, active) => {
27+
if (active)
28+
this._drainVolumeQueue();
4129
});
4230

43-
this._inhibited = false;
44-
4531
this._volumeMonitor = Gio.VolumeMonitor.get();
4632
this.enable();
4733
}
@@ -67,12 +53,21 @@ var AutomountManager = class {
6753
}
6854
}
6955

70-
async _InhibitorsChanged(_object, _senderName, [_inhibitor]) {
71-
try {
72-
const [inhibited] =
73-
await this._session.IsInhibitedAsync(GNOME_SESSION_AUTOMOUNT_INHIBIT);
74-
this._inhibited = inhibited;
75-
} catch (e) {}
56+
_onScreenLocked() {
57+
// Volumes inserted while locked will be queued
58+
}
59+
60+
_onScreenUnlocked() {
61+
this._drainVolumeQueue();
62+
}
63+
64+
_drainVolumeQueue() {
65+
while (this._volumeQueue.length > 0) {
66+
let volume = this._volumeQueue.shift();
67+
this._checkAndMountVolume(volume, {
68+
checkSession: false,
69+
});
70+
}
7671
}
7772

7873
_startupMountAll() {
@@ -90,10 +85,8 @@ var AutomountManager = class {
9085
}
9186

9287
_onDriveConnected() {
93-
// if we're not in the current ConsoleKit session,
94-
// or screensaver is active, don't play sounds
95-
// if (!this._session.SessionIsActive)
96-
// return;
88+
if (!this._loginManager.sessionIsActive)
89+
return;
9790

9891
let player = global.display.get_sound_player();
9992
player.play_from_theme('device-added-media',
@@ -102,10 +95,8 @@ var AutomountManager = class {
10295
}
10396

10497
_onDriveDisconnected() {
105-
// if we're not in the current ConsoleKit session,
106-
// or screensaver is active, don't play sounds
107-
// if (!this._session.SessionIsActive)
108-
// return;
98+
if (!this._loginManager.sessionIsActive)
99+
return;
109100

110101
let player = global.display.get_sound_player();
111102
player.play_from_theme('device-removed-media',
@@ -114,13 +105,9 @@ var AutomountManager = class {
114105
}
115106

116107
_onDriveEjectButton(monitor, drive) {
117-
// TODO: this code path is not tested, as the GVfs volume monitor
118-
// doesn't emit this signal just yet.
119-
// if (!this._session.SessionIsActive)
120-
// return;
108+
if (!this._loginManager.sessionIsActive)
109+
return;
121110

122-
// we force stop/eject in this case, so we don't have to pass a
123-
// mount operation object
124111
if (drive.can_stop()) {
125112
drive.stop(Gio.MountUnmountFlags.FORCE, null, null,
126113
(o, res) => {
@@ -147,34 +134,28 @@ var AutomountManager = class {
147134
}
148135

149136
_checkAndMountVolume(volume, params) {
150-
global.log("check and mount");
151137
params = Params.parse(params, {
152138
checkSession: true,
153139
useMountOp: true,
154140
allowAutorun: true,
155141
});
156142

157143
if (params.checkSession) {
158-
// if we're not in the current ConsoleKit session,
159-
// don't attempt automount
160-
// if (!this._session.SessionIsActive)
161-
// return;
162-
}
144+
if (!this._loginManager.sessionIsActive)
145+
return;
163146

164-
if (this._inhibited)
165-
return;
147+
if (this._loginManager.isLocked) {
148+
this._volumeQueue.push(volume);
149+
return;
150+
}
151+
}
166152

167-
// Volume is already mounted, don't bother.
168153
if (volume.get_mount())
169154
return;
170155

171156
if (!this._settings.get_boolean(SETTING_ENABLE_AUTOMOUNT) ||
172157
!volume.should_automount() ||
173158
!volume.can_mount()) {
174-
// allow the autorun to run anyway; this can happen if the
175-
// mount gets added programmatically later, even if
176-
// should_automount() or can_mount() are false, like for
177-
// blank optical media.
178159
this._allowAutorun(volume);
179160
this._allowAutorunExpire(volume);
180161

@@ -201,23 +182,15 @@ var AutomountManager = class {
201182
}
202183

203184
_onVolumeMounted(volume, res) {
204-
global.log("on volume mounted");
205185
this._allowAutorunExpire(volume);
206186

207187
try {
208188
volume.mount_finish(res);
209189
this._closeOperation(volume);
210190
} catch (e) {
211-
// FIXME: we will always get G_IO_ERROR_FAILED from the gvfs udisks
212-
// backend, see https://bugs.freedesktop.org/show_bug.cgi?id=51271
213-
// To reask the password if the user input was empty or wrong, we
214-
// will check for corresponding error messages. However, these
215-
// error strings are not unique for the cases in the comments below.
216-
if (e.message.includes('No key available with this passphrase') || // cryptsetup
217-
e.message.includes('No key available to unlock device') || // udisks (no password)
218-
// libblockdev wrong password opening LUKS device
191+
if (e.message.includes('No key available with this passphrase') ||
192+
e.message.includes('No key available to unlock device') ||
219193
e.message.includes('Failed to activate device: Incorrect passphrase') ||
220-
// cryptsetup returns EINVAL in many cases, including wrong TCRYPT password/parameters
221194
e.message.includes('Failed to load device\'s parameters: Invalid argument')) {
222195
this._reaskPassword(volume);
223196
} else {
@@ -238,6 +211,8 @@ var AutomountManager = class {
238211
GLib.source_remove(volume._allowAutorunExpireId);
239212
delete volume._allowAutorunExpireId;
240213
}
214+
215+
this._volumeQueue = this._volumeQueue.filter(v => v !== volume);
241216
}
242217

243218
_reaskPassword(volume) {

0 commit comments

Comments
 (0)