~darkxst/ubuntu/saucy/gnome-shell/upstart_log

« back to all changes in this revision

Viewing changes to js/ui/grabHelper.js

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-05-31 12:01:12 UTC
  • mfrom: (1.1.49) (19.1.36 experimental)
  • Revision ID: package-import@ubuntu.com-20130531120112-ew91khxf051x9i2r
Tags: 3.8.2-1ubuntu1
* Merge with Debian (LP: #1185869, #1185721). Remaining changes:
  - debian/control.in:
    + Build-depend on libsystemd-login-dev & libsystemd-daemon-dev
    + Depend on gdm instead of gdm3
    + Don't recommend gnome-session-fallback
  - debian/patches/40_change-pam-name-to-match-gdm.patch:
  - debian/patches/revert-suspend-break.patch:
    + Disabled, not needed on Ubuntu
  - debian/patches/ubuntu-lightdm-user-switching.patch:
    + Allow user switching when using LightDM. Thanks Gerhard Stein
      for rebasing against gnome-shell 3.8!
  - debian/patches/ubuntu_lock_on_suspend.patch
    + Respect Ubuntu's lock-on-suspend setting.
      Disabled until it can be rewritten.
  - debian/patches/git_relock_screen_after_crash.patch:
    + Add Upstream fix for unlocked session after crash (LP: #1064584)
* Note that the new GNOME Classic mode (which requires installing
  gnome-shell-extensions) won't work until gnome-session 3.8 is
  available in Ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
1
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
2
2
 
3
3
const Clutter = imports.gi.Clutter;
4
4
const Gtk = imports.gi.Gtk;
10
10
const Main = imports.ui.main;
11
11
const Params = imports.misc.params;
12
12
 
13
 
function _navigateActor(actor) {
14
 
    if (!actor)
15
 
        return;
16
 
 
17
 
    let needsGrab = true;
18
 
    if (actor instanceof St.Widget)
19
 
        needsGrab = !actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
20
 
    if (needsGrab)
21
 
        actor.grab_key_focus();
22
 
}
23
 
 
24
13
// GrabHelper:
25
14
// @owner: the actor that owns the GrabHelper
 
15
// @params: optional parameters to pass to Main.pushModal()
26
16
//
27
17
// Creates a new GrabHelper object, for dealing with keyboard and pointer grabs
28
18
// associated with a set of actors.
34
24
const GrabHelper = new Lang.Class({
35
25
    Name: 'GrabHelper',
36
26
 
37
 
    _init: function(owner) {
 
27
    _init: function(owner, params) {
38
28
        this._owner = owner;
 
29
        this._modalParams = params;
39
30
 
40
31
        this._grabStack = [];
41
32
 
42
33
        this._actors = [];
43
34
        this._capturedEventId = 0;
44
 
        this._eventId = 0;
45
35
        this._keyFocusNotifyId = 0;
46
36
        this._focusWindowChangedId = 0;
47
37
        this._ignoreRelease = false;
 
38
        this._isUngrabbingCount = 0;
48
39
 
49
40
        this._modalCount = 0;
50
41
        this._grabFocusCount = 0;
76
67
    },
77
68
 
78
69
    _isWithinGrabbedActor: function(actor) {
 
70
        let currentActor = this.currentGrab.actor;
79
71
        while (actor) {
80
72
            if (this._actors.indexOf(actor) != -1)
81
73
                return true;
 
74
            if (actor == currentActor)
 
75
                return true;
82
76
            actor = actor.get_parent();
83
77
        }
84
78
        return false;
88
82
        return this._grabStack[this._grabStack.length - 1] || {};
89
83
    },
90
84
 
 
85
    get grabbed() {
 
86
        return this._grabStack.length > 0;
 
87
    },
 
88
 
 
89
    get grabStack() {
 
90
        return this._grabStack;
 
91
    },
 
92
 
91
93
    _findStackIndex: function(actor) {
92
94
        if (!actor)
93
95
            return -1;
99
101
        return -1;
100
102
    },
101
103
 
 
104
    _actorInGrabStack: function(actor) {
 
105
        while (actor) {
 
106
            let idx = this._findStackIndex(actor);
 
107
            if (idx >= 0)
 
108
                return idx;
 
109
            actor = actor.get_parent();
 
110
        }
 
111
        return -1;
 
112
    },
 
113
 
102
114
    isActorGrabbed: function(actor) {
103
115
        return this._findStackIndex(actor) >= 0;
104
116
    },
138
150
        params = Params.parse(params, { actor: null,
139
151
                                        modal: false,
140
152
                                        grabFocus: false,
 
153
                                        focus: null,
141
154
                                        onUngrab: null });
142
155
 
143
156
        let focus = global.stage.key_focus;
155
168
        if (params.grabFocus && !this._takeFocusGrab(hadFocus))
156
169
            return false;
157
170
 
158
 
        if (hadFocus || params.grabFocus)
159
 
            _navigateActor(newFocus);
160
 
 
161
171
        this._grabStack.push(params);
 
172
 
 
173
        if (params.focus) {
 
174
            params.focus.grab_key_focus();
 
175
        } else if (newFocus && (hadFocus || params.grabFocus)) {
 
176
            if (!newFocus.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
 
177
                newFocus.grab_key_focus();
 
178
        }
 
179
 
 
180
        if ((params.grabFocus || params.modal) && !this._capturedEventId)
 
181
            this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
 
182
 
162
183
        return true;
163
184
    },
164
185
 
165
186
    _takeModalGrab: function() {
166
187
        let firstGrab = (this._modalCount == 0);
167
188
        if (firstGrab) {
168
 
            if (!Main.pushModal(this._owner))
 
189
            if (!Main.pushModal(this._owner, this._modalParams))
169
190
                return false;
170
 
 
171
 
            this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
172
 
            this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
173
191
        }
174
192
 
175
193
        this._modalCount++;
181
199
        if (this._modalCount > 0)
182
200
            return;
183
201
 
184
 
        if (this._capturedEventId > 0) {
185
 
            global.stage.disconnect(this._capturedEventId);
186
 
            this._capturedEventId = 0;
187
 
        }
188
 
 
189
 
        if (this._eventId > 0) {
190
 
            global.stage.disconnect(this._eventId);
191
 
            this._eventId = 0;
192
 
        }
193
 
 
194
202
        Main.popModal(this._owner);
195
203
        global.sync_pointer();
196
204
    },
202
210
 
203
211
            this._grabbedFromKeynav = hadFocus;
204
212
            this._preGrabInputMode = global.stage_input_mode;
205
 
            this._prevFocusedWindow = metaDisplay.focus_window;
206
213
 
207
214
            if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE ||
208
215
                this._preGrabInputMode == Shell.StageInputMode.NORMAL) {
227
234
            this._keyFocusNotifyId = 0;
228
235
        }
229
236
 
230
 
        if (!this._focusWindowChanged > 0) {
 
237
        if (this._focusWindowChangedId > 0) {
231
238
            let metaDisplay = global.screen.get_display();
232
239
            metaDisplay.disconnect(this._focusWindowChangedId);
233
240
            this._focusWindowChangedId = 0;
241
248
                global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
242
249
        }
243
250
 
244
 
        if (this._prevFocusedWindow) {
245
 
            let metaDisplay = global.screen.get_display();
246
 
            if (!metaDisplay.focus_window) {
247
 
                metaDisplay.set_input_focus_window(this._prevFocusedWindow,
248
 
                                                   false, global.get_current_time());
249
 
            }
250
 
        }
 
251
        global.screen.focus_default_window(global.display.get_current_time_roundtrip());
251
252
    },
252
253
 
253
254
    // ignoreRelease:
268
269
    // If the actor that was popped from the grab stack was not the actor
269
270
    // That was passed in, this call is ignored.
270
271
    ungrab: function(params) {
271
 
        params = Params.parse(params, { actor: this.currentGrab.actor });
 
272
        params = Params.parse(params, { actor: this.currentGrab.actor,
 
273
                                        isUser: false });
272
274
 
273
275
        let grabStackIndex = this._findStackIndex(params.actor);
274
276
        if (grabStackIndex < 0)
275
277
            return;
276
278
 
 
279
        // We may get key focus changes when calling onUngrab, which
 
280
        // would cause an extra ungrab() on the next actor in the
 
281
        // stack, which is wrong. Ignore key focus changes during the
 
282
        // ungrab, and restore the saved key focus ourselves afterwards.
 
283
        // We use a count as ungrab() may be re-entrant, as onUngrab()
 
284
        // may ungrab additional actors.
 
285
        this._isUngrabbingCount++;
 
286
 
277
287
        let focus = global.stage.key_focus;
278
288
        let hadFocus = focus && this._isWithinGrabbedActor(focus);
279
289
 
286
296
            let poppedGrab = poppedGrabs[i];
287
297
 
288
298
            if (poppedGrab.onUngrab)
289
 
                poppedGrab.onUngrab();
 
299
                poppedGrab.onUngrab(params.isUser);
290
300
 
291
301
            if (poppedGrab.modal)
292
302
                this._releaseModalGrab();
295
305
                this._releaseFocusGrab();
296
306
        }
297
307
 
 
308
        if (!this.grabbed && this._capturedEventId > 0) {
 
309
            global.stage.disconnect(this._capturedEventId);
 
310
            this._capturedEventId = 0;
 
311
 
 
312
            this._ignoreRelease = false;
 
313
        }
 
314
 
298
315
        if (hadFocus) {
299
316
            let poppedGrab = poppedGrabs[0];
300
 
            _navigateActor(poppedGrab.savedFocus);
 
317
            if (poppedGrab.savedFocus)
 
318
                poppedGrab.savedFocus.grab_key_focus();
301
319
        }
 
320
 
 
321
        this._isUngrabbingCount--;
302
322
    },
303
323
 
304
324
    _onCapturedEvent: function(actor, event) {
305
325
        let type = event.type();
 
326
 
 
327
        if (type == Clutter.EventType.KEY_PRESS &&
 
328
            event.get_key_symbol() == Clutter.KEY_Escape) {
 
329
            this.ungrab({ isUser: true });
 
330
            return true;
 
331
        }
 
332
 
306
333
        let press = type == Clutter.EventType.BUTTON_PRESS;
307
334
        let release = type == Clutter.EventType.BUTTON_RELEASE;
308
335
        let button = press || release;
309
336
 
310
337
        if (release && this._ignoreRelease) {
311
338
            this._ignoreRelease = false;
312
 
            return false;
 
339
            return true;
313
340
        }
314
341
 
315
342
        if (!button && this._modalCount == 0)
326
353
            // which should be a release event.
327
354
            if (press)
328
355
                this._ignoreRelease = true;
329
 
            this.ungrab({ actor: this._grabStack[0].actor });
 
356
            let i = this._actorInGrabStack(event.get_source()) + 1;
 
357
            this.ungrab({ actor: this._grabStack[i].actor, isUser: true });
 
358
            return true;
330
359
        }
331
360
 
332
361
        return this._modalCount > 0;
333
362
    },
334
363
 
335
 
    // We catch 'event' rather than 'key-press-event' so that we get
336
 
    // a chance to run before the overview's own Escape check
337
 
    _onEvent: function(actor, event) {
338
 
        if (event.type() == Clutter.EventType.KEY_PRESS &&
339
 
            event.get_key_symbol() == Clutter.KEY_Escape) {
340
 
            this.ungrab();
341
 
            return true;
342
 
        }
343
 
 
344
 
        return false;
345
 
    },
346
 
 
347
364
    _onKeyFocusChanged: function() {
 
365
        if (this._isUngrabbingCount > 0)
 
366
            return;
 
367
 
348
368
        let focus = global.stage.key_focus;
349
369
        if (!focus || !this._isWithinGrabbedActor(focus))
350
 
            this.ungrab();
 
370
            this.ungrab({ isUser: true });
351
371
    },
352
372
 
353
373
    _focusWindowChanged: function() {
354
374
        let metaDisplay = global.screen.get_display();
355
375
        if (metaDisplay.focus_window != null)
356
 
            this.ungrab();
 
376
            this.ungrab({ isUser: true });
357
377
    }
358
378
});