cb4ad9a963
We had problems because the More links were reacting on press but other elements were reacting on release. (Often the link would trigger *and* an item.) Just connecting to ::button-release-event on ClutterText gives a stuck grab (since ClutterText gets the press but not the release), so we need more complicated code that we encapsulate into a new class. link.js: new "pseudo-widget" that implements a clickable link. overlay.js: Use Link.Link for the More.. links http://bugzilla.gnome.org/show_bug.cgi?id=573323
82 lines
2.5 KiB
JavaScript
82 lines
2.5 KiB
JavaScript
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
const Clutter = imports.gi.Clutter;
|
|
const Lang = imports.lang;
|
|
const Signals = imports.signals;
|
|
|
|
// Link is a clickable link. Right now it just handles properly capturing
|
|
// press and release events and short-circuiting the button handling in
|
|
// ClutterText, but more features like different colors for hover/pressed states
|
|
// or a different mouse cursor could be implemented.
|
|
//
|
|
// The properties passed in are forwarded to the Clutter.Text() constructor,
|
|
// so can include, 'text', 'font_name', etc.
|
|
function Link(props) {
|
|
this._init(props);
|
|
}
|
|
|
|
Link.prototype = {
|
|
_init : function(props) {
|
|
let realProps = { reactive: true };
|
|
// The user can pass in reactive: false to override the above and get
|
|
// a non-reactive link (a link to the current page, perhaps)
|
|
Lang.copyProperties(props, realProps);
|
|
|
|
this.actor = new Clutter.Text(realProps);
|
|
this.actor._delegate = this;
|
|
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
|
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
|
|
this.actor.connect('enter-event', Lang.bind(this, this._onEnter));
|
|
this.actor.connect('leave-event', Lang.bind(this, this._onLeave));
|
|
|
|
this._buttonDown = false;
|
|
this._havePointer = false;
|
|
},
|
|
|
|
// Update the text of the link
|
|
setText : function(text) {
|
|
this.actor.text = text;
|
|
},
|
|
|
|
// We want to react on buttonDown, but if we override button-release-event for
|
|
// ClutterText, but not button-press-event, we get a stuck grab. Tracking
|
|
// buttonDown and doing the grab isn't really necessary, but doing it makes
|
|
// the behavior perfectly correct if the user clicks on one actor, drags
|
|
// to another and releases - that should not trigger either actor.
|
|
_onButtonPress : function(actor, event) {
|
|
this._buttonDown = true;
|
|
this._havePointer = true; // Hack to work around poor enter/leave tracking in Clutter
|
|
Clutter.grab_pointer(actor);
|
|
|
|
return true;
|
|
},
|
|
|
|
_onButtonRelease : function(actor, event) {
|
|
if (this._buttonDown) {
|
|
this._buttonDown = false;
|
|
Clutter.ungrab_pointer(actor);
|
|
|
|
if (this._havePointer)
|
|
this.emit('clicked');
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
_onEnter : function(actor, event) {
|
|
if (event.get_source() == actor)
|
|
this._havePointer = true;
|
|
|
|
return false;
|
|
},
|
|
|
|
_onLeave : function(actor, event) {
|
|
if (event.get_source() == actor)
|
|
this._havePointer = false;
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
Signals.addSignalMethods(Link.prototype);
|