pieTimer: Use custom GObject property for animating pie

Before the move to Clutters implicit animations with 0846238f6 and
bf497ed64, we used Tweener to do a fake-animation of the opacity and
Tweeners `onUpdate` signal to queue a repaint of the PieTimer everytime
Tweener tries to update the animation.

Now, with Clutters implicit animations, there is no `onUpdate` signal
anymore and also `notify::opacity` no longer gets emitted since the
value doesn't actually change. This lead to the PieTimer no longer being
repainted, which broke the animation.

Fix this by implementing the current angle of the pie using a custom
GObject property `angle` and animating this property using the new
`actor.ease_property` method.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1533
This commit is contained in:
Jonas Dreßler 2019-08-21 16:47:38 +02:00
parent 10c1df61cd
commit 5cb02c1cb5

View File

@ -3,21 +3,37 @@ const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const Cairo = imports.cairo; const Cairo = imports.cairo;
var PieTimer = GObject.registerClass( var PieTimer = GObject.registerClass({
class PieTimer extends St.DrawingArea { Properties: {
'angle': GObject.ParamSpec.double(
'angle', 'angle', 'angle',
GObject.ParamFlags.READWRITE,
0, 2 * Math.PI, 0)
}
}, class PieTimer extends St.DrawingArea {
_init() { _init() {
this._x = 0; this._x = 0;
this._y = 0; this._y = 0;
this._startTime = 0; this._angle = 0;
this._duration = 0;
super._init({ super._init({
style_class: 'pie-timer', style_class: 'pie-timer',
visible: false, visible: false,
can_focus: false, can_focus: false,
reactive: false reactive: false
}); });
}
this.connect('notify::opacity', this.queue_repaint.bind(this)); get angle() {
return this._angle;
}
set angle(angle) {
if (this._angle == angle)
return;
this._angle = angle;
this.notify('angle');
this.queue_repaint();
} }
vfunc_repaint() { vfunc_repaint() {
@ -28,11 +44,8 @@ class PieTimer extends St.DrawingArea {
let [width, height] = this.get_surface_size(); let [width, height] = this.get_surface_size();
let radius = Math.min(width / 2, height / 2); let radius = Math.min(width / 2, height / 2);
let currentTime = GLib.get_monotonic_time() / 1000.0;
let ellapsed = currentTime - this._startTime;
let angle = (ellapsed / this._duration) * 2 * Math.PI;
let startAngle = 3 * Math.PI / 2; let startAngle = 3 * Math.PI / 2;
let endAngle = startAngle + angle; let endAngle = startAngle + this._angle;
let cr = this.get_context(); let cr = this.get_context();
cr.setLineCap(Cairo.LineCap.ROUND); cr.setLineCap(Cairo.LineCap.ROUND);
@ -60,16 +73,14 @@ class PieTimer extends St.DrawingArea {
this.x = x - this.width / 2; this.x = x - this.width / 2;
this.y = y - this.height / 2; this.y = y - this.height / 2;
this._angle = 0;
this.show(); this.show();
Main.uiGroup.set_child_above_sibling(this, null); Main.uiGroup.set_child_above_sibling(this, null);
this._startTime = GLib.get_monotonic_time() / 1000.0; this.ease_property('angle', 2 * Math.PI, {
this._duration = duration;
this.ease({
opacity: 255,
duration, duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.LINEAR,
onComplete: () => this.stop() onComplete: () => this.stop()
}); });
} }