Locate pointer (#905)

This commit is contained in:
David Hewitt 2020-08-25 18:35:32 +01:00 committed by GitHub
parent 992544a524
commit a44e26cb7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 160 additions and 0 deletions

View File

@ -0,0 +1,143 @@
//
// Copyright 2020 elementary, Inc. (https://elementary.io)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
namespace Gala {
public class PointerLocator : Clutter.Actor, Clutter.Animatable {
private const int WIDTH_PX = 300;
private const int HEIGHT_PX = 300;
private const int ANIMATION_TIME_MS = 300;
private const uint BORDER_WIDTH_PX = 3;
private const string BACKGROUND_COLOR = "#64baff";
private const double BACKGROUND_OPACITY = 0.7;
public weak WindowManager wm { get; construct; }
private int scaling_factor = 1;
private GLib.Settings settings;
private Cogl.Pipeline pipeline;
private Cairo.Pattern stroke_color;
private Cairo.Pattern fill_color;
private uint timeout_id;
public PointerLocator (WindowManager wm) {
Object (wm: wm);
}
construct {
visible = false;
reactive = false;
settings = new GLib.Settings ("org.gnome.desktop.interface");
pipeline = new Cogl.Pipeline (Clutter.get_default_backend ().get_cogl_context ());
scaling_factor = InternalUtils.get_ui_scaling_factor ();
set_size (WIDTH_PX * scaling_factor, HEIGHT_PX * scaling_factor);
var rgba = Gdk.RGBA ();
rgba.parse (BACKGROUND_COLOR);
stroke_color = new Cairo.Pattern.rgb (rgba.red, rgba.green, rgba.blue);
fill_color = new Cairo.Pattern.rgba (rgba.red, rgba.green, rgba.blue, BACKGROUND_OPACITY);
}
public override void paint (Clutter.PaintContext context) {
var width = WIDTH_PX * scaling_factor;
var height = HEIGHT_PX * scaling_factor;
var radius = int.min (width / 2, height / 2);
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
var cr = new Cairo.Context (surface);
cr.set_line_cap (Cairo.LineCap.ROUND);
cr.set_line_join (Cairo.LineJoin.ROUND);
cr.translate (width / 2, height / 2);
cr.move_to (radius - BORDER_WIDTH_PX, 0);
cr.arc (0, 0, radius - BORDER_WIDTH_PX * scaling_factor, 0, 2 * Math.PI);
cr.close_path ();
cr.set_line_width (0);
cr.set_source (fill_color);
cr.fill_preserve ();
cr.set_line_width (BORDER_WIDTH_PX * scaling_factor);
cr.set_source (stroke_color);
cr.stroke ();
var cogl_context = context.get_framebuffer ().get_context ();
try {
var texture = new Cogl.Texture2D.from_data (cogl_context, width, height, Cogl.PixelFormat.BGRA_8888_PRE,
surface.get_stride (), surface.get_data ());
pipeline.set_layer_texture (0, texture);
context.get_framebuffer ().draw_rectangle (pipeline, 0, 0, width, height);
} catch (Error e) {}
base.paint (context);
}
public void show_ripple () {
if (!settings.get_boolean ("locate-pointer")) {
return;
}
if (timeout_id != 0) {
GLib.Source.remove (timeout_id);
timeout_id = 0;
visible = false;
restore_easing_state ();
}
var tracker = wm.get_display ().get_cursor_tracker ();
int x, y;
tracker.get_pointer (out x, out y, null);
this.x = x - (width / 2);
this.y = y - (width / 2);
var pivot = Graphene.Point ();
pivot.x = 0.5f;
pivot.y = 0.5f;
pivot_point = pivot;
scale_x = 1;
scale_y = 1;
visible = true;
save_easing_state ();
set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
set_easing_duration (ANIMATION_TIME_MS);
timeout_id = Timeout.add (ANIMATION_TIME_MS, () => {
timeout_id = 0;
restore_easing_state ();
return GLib.Source.REMOVE;
});
scale_x = 0;
scale_y = 0;
}
}
}

View File

@ -58,6 +58,10 @@ namespace Gala {
public ScreenShield? screen_shield { get; private set; }
#if HAS_MUTTER336
public PointerLocator pointer_locator { get; private set; }
#endif
Meta.PluginInfo info;
WindowSwitcher? winswitcher = null;
@ -244,6 +248,12 @@ namespace Gala {
#else
top_window_group = screen.get_top_window_group ();
#endif
#if HAS_MUTTER336
pointer_locator = new PointerLocator (this);
ui_group.add_child (pointer_locator);
#endif
ui_group.add_child (screen_shield);
stage.remove_child (top_window_group);
@ -2176,6 +2186,12 @@ namespace Gala {
end_switch_workspace ();
}
#if HAS_MUTTER336
public override void locate_pointer () {
pointer_locator.show_ripple ();
}
#endif
public override bool keybinding_filter (Meta.KeyBinding binding) {
if (!is_modal ())
return false;

View File

@ -28,6 +28,7 @@ gala_bin_sources = files(
'Widgets/MonitorClone.vala',
'Widgets/MultitaskingView.vala',
'Widgets/PixelPicker.vala',
'Widgets/PointerLocator.vala',
'Widgets/SafeWindowClone.vala',
'Widgets/ScreenShield.vala',
'Widgets/SelectionArea.vala',