2023-07-10 09:53:00 +00:00
|
|
|
import Clutter from 'gi://Clutter';
|
|
|
|
import GObject from 'gi://GObject';
|
|
|
|
import Meta from 'gi://Meta';
|
|
|
|
import St from 'gi://St';
|
|
|
|
import * as Main from './main.js';
|
|
|
|
import Cairo from 'gi://cairo';
|
2019-03-20 16:46:12 +00:00
|
|
|
|
2019-08-22 08:25:19 +00:00
|
|
|
const SUCCESS_ZOOM_OUT_DURATION = 150;
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const PieTimer = GObject.registerClass({
|
2019-08-21 14:47:38 +00:00
|
|
|
Properties: {
|
|
|
|
'angle': GObject.ParamSpec.double(
|
|
|
|
'angle', 'angle', 'angle',
|
|
|
|
GObject.ParamFlags.READWRITE,
|
2019-08-20 21:43:54 +00:00
|
|
|
0, 2 * Math.PI, 0),
|
|
|
|
},
|
2019-08-21 14:47:38 +00:00
|
|
|
}, class PieTimer extends St.DrawingArea {
|
2019-03-20 16:46:12 +00:00
|
|
|
_init() {
|
2019-08-21 14:47:38 +00:00
|
|
|
this._angle = 0;
|
2019-07-26 00:25:32 +00:00
|
|
|
super._init({
|
|
|
|
style_class: 'pie-timer',
|
2019-08-25 16:02:14 +00:00
|
|
|
opacity: 0,
|
2019-07-26 00:25:32 +00:00
|
|
|
visible: false,
|
|
|
|
can_focus: false,
|
2019-08-20 21:43:54 +00:00
|
|
|
reactive: false,
|
2019-07-26 00:25:32 +00:00
|
|
|
});
|
2019-08-22 08:25:19 +00:00
|
|
|
|
|
|
|
this.set_pivot_point(0.5, 0.5);
|
2019-08-21 14:47:38 +00:00
|
|
|
}
|
2019-07-26 00:28:40 +00:00
|
|
|
|
2019-08-21 14:47:38 +00:00
|
|
|
get angle() {
|
|
|
|
return this._angle;
|
|
|
|
}
|
|
|
|
|
|
|
|
set angle(angle) {
|
2023-08-07 00:51:19 +00:00
|
|
|
if (this._angle === angle)
|
2019-08-21 14:47:38 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
this._angle = angle;
|
|
|
|
this.notify('angle');
|
|
|
|
this.queue_repaint();
|
2019-03-20 16:46:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vfunc_repaint() {
|
|
|
|
let node = this.get_theme_node();
|
|
|
|
let backgroundColor = node.get_color('-pie-background-color');
|
|
|
|
let borderColor = node.get_color('-pie-border-color');
|
|
|
|
let borderWidth = node.get_length('-pie-border-width');
|
|
|
|
let [width, height] = this.get_surface_size();
|
|
|
|
let radius = Math.min(width / 2, height / 2);
|
|
|
|
|
|
|
|
let startAngle = 3 * Math.PI / 2;
|
2019-08-21 14:47:38 +00:00
|
|
|
let endAngle = startAngle + this._angle;
|
2019-03-20 16:46:12 +00:00
|
|
|
|
|
|
|
let cr = this.get_context();
|
|
|
|
cr.setLineCap(Cairo.LineCap.ROUND);
|
|
|
|
cr.setLineJoin(Cairo.LineJoin.ROUND);
|
|
|
|
cr.translate(width / 2, height / 2);
|
|
|
|
|
2019-08-22 08:05:40 +00:00
|
|
|
if (this._angle < 2 * Math.PI)
|
|
|
|
cr.moveTo(0, 0);
|
|
|
|
|
2019-03-20 16:46:12 +00:00
|
|
|
cr.arc(0, 0, radius - borderWidth, startAngle, endAngle);
|
2019-08-22 08:05:40 +00:00
|
|
|
|
|
|
|
if (this._angle < 2 * Math.PI)
|
|
|
|
cr.lineTo(0, 0);
|
|
|
|
|
2019-03-20 16:46:12 +00:00
|
|
|
cr.closePath();
|
|
|
|
|
|
|
|
cr.setLineWidth(0);
|
|
|
|
Clutter.cairo_set_source_color(cr, backgroundColor);
|
|
|
|
cr.fillPreserve();
|
|
|
|
|
|
|
|
cr.setLineWidth(borderWidth);
|
|
|
|
Clutter.cairo_set_source_color(cr, borderColor);
|
|
|
|
cr.stroke();
|
|
|
|
|
|
|
|
cr.$dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
start(x, y, duration) {
|
|
|
|
this.x = x - this.width / 2;
|
|
|
|
this.y = y - this.height / 2;
|
|
|
|
this.show();
|
|
|
|
|
2019-08-22 08:02:42 +00:00
|
|
|
this.ease({
|
|
|
|
opacity: 255,
|
|
|
|
duration: duration / 4,
|
2019-08-20 21:43:54 +00:00
|
|
|
mode: Clutter.AnimationMode.EASE_IN_QUAD,
|
2019-08-22 08:02:42 +00:00
|
|
|
});
|
|
|
|
|
2019-08-21 14:47:38 +00:00
|
|
|
this.ease_property('angle', 2 * Math.PI, {
|
2018-07-20 19:46:19 +00:00
|
|
|
duration,
|
2019-08-21 14:47:38 +00:00
|
|
|
mode: Clutter.AnimationMode.LINEAR,
|
2019-08-20 21:43:54 +00:00
|
|
|
onComplete: this._onTransitionComplete.bind(this),
|
2019-08-22 08:25:19 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_onTransitionComplete() {
|
|
|
|
this.ease({
|
|
|
|
scale_x: 2,
|
|
|
|
scale_y: 2,
|
|
|
|
opacity: 0,
|
|
|
|
duration: SUCCESS_ZOOM_OUT_DURATION,
|
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
2019-08-20 21:43:54 +00:00
|
|
|
onStopped: () => this.destroy(),
|
2018-07-20 19:46:19 +00:00
|
|
|
});
|
2019-03-20 16:46:12 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
export class PointerA11yTimeout {
|
2019-03-20 16:46:12 +00:00
|
|
|
constructor() {
|
2019-10-05 10:35:21 +00:00
|
|
|
let seat = Clutter.get_default_backend().get_default_seat();
|
2019-03-20 16:46:12 +00:00
|
|
|
|
2019-10-05 10:35:21 +00:00
|
|
|
seat.connect('ptr-a11y-timeout-started', (o, device, type, timeout) => {
|
2019-02-01 13:41:55 +00:00
|
|
|
let [x, y] = global.get_pointer();
|
2019-08-25 16:02:14 +00:00
|
|
|
|
|
|
|
this._pieTimer = new PieTimer();
|
|
|
|
Main.uiGroup.add_actor(this._pieTimer);
|
|
|
|
Main.uiGroup.set_child_above_sibling(this._pieTimer, null);
|
|
|
|
|
|
|
|
this._pieTimer.start(x, y, timeout);
|
|
|
|
|
2023-08-07 00:51:19 +00:00
|
|
|
if (type === Clutter.PointerA11yTimeoutType.GESTURE)
|
2019-01-29 19:36:54 +00:00
|
|
|
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
|
2019-03-20 16:46:12 +00:00
|
|
|
});
|
|
|
|
|
2019-10-05 10:35:21 +00:00
|
|
|
seat.connect('ptr-a11y-timeout-stopped', (o, device, type, clicked) => {
|
2019-08-22 08:10:23 +00:00
|
|
|
if (!clicked)
|
2019-08-25 16:02:14 +00:00
|
|
|
this._pieTimer.destroy();
|
2019-08-22 08:10:23 +00:00
|
|
|
|
2023-08-07 00:51:19 +00:00
|
|
|
if (type === Clutter.PointerA11yTimeoutType.GESTURE)
|
2019-01-29 19:36:54 +00:00
|
|
|
global.display.set_cursor(Meta.Cursor.DEFAULT);
|
2019-03-20 16:46:12 +00:00
|
|
|
});
|
|
|
|
}
|
2023-07-10 09:53:00 +00:00
|
|
|
}
|