3

I want to build a Gnome shell extension that highlights the mouse cursor. I have a working prototype of a Clutter Actor that draws above all other windows, but mouse movements are only tracked when no other windows are behind the test canvas.

My impression is that the drawing is in the foreground but pointer signals are in the background. I would like to raise the move-signals to the very foreground in order to track the movement and update the position of the highlighting while staying transparent for all other UI interactions, so users can normally use the desktop while the mouse cursor highlighting is turned on.

Bonus question: is this even the right approach to do this?

Here is my prototype (https://github.com/tobias47n9e/MouseHighlight):

const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Lang = imports.lang;
const PanelMenu = imports.ui.panelMenu;
const Clutter = imports.gi.Clutter;
const Mainloop = imports.mainloop;
const Cairo = imports.cairo;

let mouse_highlight;

/**
* Main shell extension object.
*/
const MouseHighlight = new Lang.Class({
    Name: 'MouseHighlight',
    Extends: PanelMenu.Button,

    /**
    * Initializes the shell extension object.
    */
    _init: function() {
        this.parent(0.0, "MouseHighlight");
        this.offset = [1000, 500];
        this.cnvs_size = [200, 200];

        this.label = new St.Label({
            text: "Choose Highlighting",
            y_expand: true,
            y_align: Clutter.ActorAlign.CENTER
        });

        this.actor.add_actor(this.label);

        this.cnvs_actor = new Clutter.Actor();

        this.setup_cnvs_actor();
    },

    /**
    * Sets the size, background and offset of canvas actor. Shows it and
    * adds it to the main uiGroup. Connects the signals of the actor.
    */
    setup_cnvs_actor: function () {
        let color = new Clutter.Color({
            red: 255,
            green: 0,
            blue: 0,
            alpha: 128
        });

        this.cnvs_actor.set_position(this.offset[0], this.offset[1]);
        this.cnvs_actor.set_width(this.cnvs_size[0]);
        this.cnvs_actor.set_height(this.cnvs_size[1]);
        this.cnvs_actor.set_background_color(color);
        this.cnvs_actor.show_all();
        this.cnvs_actor.set_reactive(true);
        this.cnvs_actor.connect("motion-event", this.mouse_move.bind(this));
        Main.uiGroup.add_actor(this.cnvs_actor);
    },

    /**
    * Draws a point at certain coordinates and offset. Called by
    * click events on the canvas.
    */
    draw_point: function(canvas, cr, width, height, coords, offset, draw) {
        let x = coords[0] - offset[0];
        let y = coords[1] - offset[1];

        cr.save();
        cr.setOperator(Cairo.Operator.CLEAR);
        cr.paint();
        cr.restore();
        cr.setOperator(Cairo.Operator.OVER);
        cr.setLineCap(Cairo.LineCap.ROUND);
        cr.setLineWidth(10);

        cr.translate(x, y);
        cr.arc(0, 0, 5, 0, Math.PI * 2);
        cr.stroke();

        return draw;
    },

    /**
    * Runs when the mouse moves over the canvas. Calls a function that
    * draw a highlight under the mouse cursor.
    */
    mouse_move: function(actor, event) {
        let coords = event.get_coords();
        let self = this;

        let canvas = new Clutter.Canvas();
        canvas.set_size(this.cnvs_size[0],this.cnvs_size[1]);

        canvas.connect("draw", function(canvas, cr, width, height) {
            self.draw_point(canvas, cr, width, height, coords, self.offset, false);
        });

        canvas.invalidate();

        this.cnvs_actor.set_content(canvas);
    },

    destroy: function() {
        this.parent();
        this.cnvs_actor.destroy();
    },
});

/**
* Initializes the shell extension.
*/
function init() {

}

/**
* Runs when the shell extension is enabled.
*/
function enable() {
    mouse_highlight = new MouseHighlight();

    Main.panel.addToStatusArea('mouse-highlight', mouse_highlight, 1, 'right');
}

/**
* Runs when the shell extension is disabled.
*/
function disable() {
    mouse_highlight.destroy();
}
daOnlyBG
  • 595
  • 4
  • 20
  • 49
tobias47n9e
  • 2,233
  • 3
  • 28
  • 54

0 Answers0