pointerWatcher: add a class to track the pointer
Add a class to efficiently poll the pointer position, stopping polling when the user is idle. https://bugzilla.gnome.org/show_bug.cgi?id=682310
This commit is contained in:
parent
3776c50986
commit
446583400e
@ -72,6 +72,7 @@ nobase_dist_js_DATA = \
|
|||||||
ui/panel.js \
|
ui/panel.js \
|
||||||
ui/panelMenu.js \
|
ui/panelMenu.js \
|
||||||
ui/placeDisplay.js \
|
ui/placeDisplay.js \
|
||||||
|
ui/pointerWatcher.js \
|
||||||
ui/polkitAuthenticationAgent.js \
|
ui/polkitAuthenticationAgent.js \
|
||||||
ui/popupMenu.js \
|
ui/popupMenu.js \
|
||||||
ui/remoteSearch.js \
|
ui/remoteSearch.js \
|
||||||
|
126
js/ui/pointerWatcher.js
Normal file
126
js/ui/pointerWatcher.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||||
|
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
|
||||||
|
// We stop polling if the user is idle for more than this amount of time
|
||||||
|
const IDLE_TIME = 1000;
|
||||||
|
|
||||||
|
// This file implements a reasonably efficient system for tracking the position
|
||||||
|
// of the mouse pointer. We simply query the pointer from the X server in a loop,
|
||||||
|
// but we turn off the polling when the user is idle.
|
||||||
|
|
||||||
|
let _pointerWatcher = null;
|
||||||
|
function getPointerWatcher() {
|
||||||
|
if (_pointerWatcher == null)
|
||||||
|
_pointerWatcher = new PointerWatcher();
|
||||||
|
|
||||||
|
return _pointerWatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PointerWatch = new Lang.Class({
|
||||||
|
Name: 'PointerWatch',
|
||||||
|
|
||||||
|
_init: function(watcher, interval, callback) {
|
||||||
|
this.watcher = watcher;
|
||||||
|
this.interval = interval;
|
||||||
|
this.callback = callback;
|
||||||
|
},
|
||||||
|
|
||||||
|
// remove:
|
||||||
|
// remove this watch. This function may safely be called
|
||||||
|
// while the callback is executing.
|
||||||
|
remove: function() {
|
||||||
|
this.watcher._removeWatch(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const PointerWatcher = new Lang.Class({
|
||||||
|
Name: 'PointerWatcher',
|
||||||
|
|
||||||
|
_init: function() {
|
||||||
|
let idleMonitor = Shell.IdleMonitor.get();
|
||||||
|
idleMonitor.add_watch(IDLE_TIME,
|
||||||
|
Lang.bind(this, this._onIdleMonitorWatch));
|
||||||
|
this._idle = idleMonitor.get_idletime() > IDLE_TIME;
|
||||||
|
this._watches = [];
|
||||||
|
this.pointerX = null;
|
||||||
|
this.pointerY = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// addWatch:
|
||||||
|
// @interval: hint as to the time resolution needed. When the user is
|
||||||
|
// not idle, the position of the pointer will be queried at least
|
||||||
|
// once every this many milliseconds.
|
||||||
|
// @callback: function to call when the pointer position changes - takes
|
||||||
|
// two arguments, X and Y.
|
||||||
|
//
|
||||||
|
// Set up a watch on the position of the mouse pointer. Returns a
|
||||||
|
// PointerWatch object which has a remove() method to remove the watch.
|
||||||
|
addWatch: function(interval, callback) {
|
||||||
|
// Avoid unreliably calling the watch for the current position
|
||||||
|
this._updatePointer();
|
||||||
|
|
||||||
|
let watch = new PointerWatch(this, interval, callback);
|
||||||
|
this._watches.push(watch);
|
||||||
|
this._updateTimeout();
|
||||||
|
return watch;
|
||||||
|
},
|
||||||
|
|
||||||
|
_removeWatch: function(watch) {
|
||||||
|
for (let i = 0; i < this._watches.length; i++) {
|
||||||
|
if (this._watches[i] == watch) {
|
||||||
|
this._watches.splice(i, 1);
|
||||||
|
this._updateTimeout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onIdleMonitorWatch: function(monitor, id, userBecameIdle) {
|
||||||
|
this._idle = userBecameIdle;
|
||||||
|
if (!userBecameIdle)
|
||||||
|
this._updatePointer();
|
||||||
|
|
||||||
|
this._updateTimeout();
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateTimeout: function() {
|
||||||
|
if (this._timeoutId) {
|
||||||
|
Mainloop.source_remove(this._timeoutId);
|
||||||
|
this._timeoutId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._idle || this._watches.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let minInterval = this._watches[0].interval;
|
||||||
|
for (let i = 1; i < this._watches.length; i++)
|
||||||
|
minInterval = Math.min(this._watches[i].interval, minInterval);
|
||||||
|
|
||||||
|
this._timeoutId = Mainloop.timeout_add(minInterval,
|
||||||
|
Lang.bind(this, this._onTimeout));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onTimeout: function() {
|
||||||
|
this._updatePointer();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updatePointer: function() {
|
||||||
|
let [x, y, mods] = global.get_pointer();
|
||||||
|
if (this.pointerX == x && this.pointerY == y)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.pointerX = x;
|
||||||
|
this.pointerY = y;
|
||||||
|
|
||||||
|
for (let i = 0; i < this._watches.length;) {
|
||||||
|
let watch = this._watches[i];
|
||||||
|
watch.callback(x, y);
|
||||||
|
if (watch == this._watches[i]) // guard against self-removal
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user