Commit 6dff93a0 authored by Olivier Fourdan's avatar Olivier Fourdan

mouse: remove locate-pointer

The current implementation in gnome-settings-daemon relies on X11
and cannot work on Wayland.

Remove the locate-pointer functionality and the relevant helper from
gnome-settings-daemon to move to the Wayland compositor instead, i.e.
mutter/gnome-shell.

Also, move the gsettings key for "locate-pointer" to "org.gnome.desktop.
interface".

!86
gsettings-desktop-schemas!19
mutter!453
gnome-shell#981
parent c23c5c20
Pipeline #87159 passed with stages
in 46 minutes and 54 seconds
......@@ -87,7 +87,6 @@ plugins/smartcard/org.gnome.ScreenSaver.c
plugins/smartcard/org.gnome.ScreenSaver.h
plugins/smartcard/org.gnome.SessionManager.c
plugins/smartcard/org.gnome.SessionManager.h
plugins/mouse/gsd-locate-pointer
plugins/mouse/gsd-test-mouse
plugins/power/gsd-backlight-helper
plugins/power/gsd-power-enums-update
......
......@@ -30,7 +30,6 @@ volume-up = /apps/gnome_settings_daemon/keybindings/volume_up
www = /apps/gnome_settings_daemon/keybindings/www
[org.gnome.settings-daemon.peripherals.mouse]
locate-pointer = /desktop/gnome/peripherals/mouse/locate_pointer
double-click = /desktop/gnome/peripherals/mouse/double_click
drag-threshold = /desktop/gnome/peripherals/mouse/drag_threshold
......
......@@ -47,10 +47,6 @@
</key>
</schema>
<schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.peripherals.mouse" path="/org/gnome/settings-daemon/peripherals/mouse/">
<key name="locate-pointer" type="b">
<default>false</default>
<summary>Highlights the current location of the pointer when the Control key is pressed and released.</summary>
</key>
<key name="double-click" type="i">
<default>400</default>
<summary>Double click time</summary>
......
/* gsd-locate-pointer.c
*
* Copyright (C) 2008 Carlos Garnacho <carlos@imendio.com>
*
* 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 2 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/>.
*/
#include <gtk/gtk.h>
#include "gsd-timeline.h"
#include "gsd-locate-pointer.h"
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkx.h>
#include <X11/keysym.h>
#define ANIMATION_LENGTH 750
#define WINDOW_SIZE 101
#define N_CIRCLES 4
/* All circles are supposed to be moving when progress
* reaches 0.5, and each of them are supposed to long
* for half of the progress, hence the need of 0.5 to
* get the circles interval, and the multiplication
* by 2 to know a circle progress */
#define CIRCLES_PROGRESS_INTERVAL (0.5 / N_CIRCLES)
#define CIRCLE_PROGRESS(p) (MIN (1., ((gdouble) (p) * 2.)))
typedef struct GsdLocatePointerData GsdLocatePointerData;
struct GsdLocatePointerData
{
GsdTimeline *timeline;
GtkWidget *widget;
GdkWindow *window;
gdouble progress;
};
static GsdLocatePointerData *data = NULL;
static void
locate_pointer_paint (GsdLocatePointerData *data,
cairo_t *cr,
gboolean composite)
{
GdkRGBA color;
gdouble progress, circle_progress;
gint width, height, i;
GtkStyleContext *context;
progress = data->progress;
width = gdk_window_get_width (data->window);
height = gdk_window_get_height (data->window);
context = gtk_widget_get_style_context (data->widget);
gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED, &color);
cairo_set_source_rgba (cr, 1., 1., 1., 0.);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
for (i = 0; i <= N_CIRCLES; i++)
{
if (progress < 0.)
break;
circle_progress = MIN (1., (progress * 2));
progress -= CIRCLES_PROGRESS_INTERVAL;
if (circle_progress >= 1.)
continue;
if (composite)
{
cairo_set_source_rgba (cr,
color.red,
color.green,
color.blue,
1 - circle_progress);
cairo_arc (cr,
width / 2,
height / 2,
circle_progress * width / 2,
0, 2 * G_PI);
cairo_fill (cr);
}
else
{
cairo_set_source_rgb (cr, 0., 0., 0.);
cairo_set_line_width (cr, 3.);
cairo_arc (cr,
width / 2,
height / 2,
circle_progress * width / 2,
0, 2 * G_PI);
cairo_stroke (cr);
cairo_set_source_rgb (cr, 1., 1., 1.);
cairo_set_line_width (cr, 1.);
cairo_arc (cr,
width / 2,
height / 2,
circle_progress * width / 2,
0, 2 * G_PI);
cairo_stroke (cr);
}
}
}
static gboolean
locate_pointer_draw (GtkWidget *widget,
cairo_t *cr,
gpointer user_data)
{
GsdLocatePointerData *data = (GsdLocatePointerData *) user_data;
if (gtk_cairo_should_draw_window (cr, data->window))
locate_pointer_paint (data, cr, gtk_widget_is_composited (data->widget));
return TRUE;
}
static void
update_shape (GsdLocatePointerData *data)
{
cairo_t *cr;
cairo_region_t *region;
cairo_surface_t *mask;
mask = cairo_image_surface_create (CAIRO_FORMAT_A1, WINDOW_SIZE, WINDOW_SIZE);
cr = cairo_create (mask);
locate_pointer_paint (data, cr, FALSE);
region = gdk_cairo_region_create_from_surface (mask);
gdk_window_shape_combine_region (data->window, region, 0, 0);
cairo_region_destroy (region);
cairo_destroy (cr);
cairo_surface_destroy (mask);
}
static void
timeline_frame_cb (GsdTimeline *timeline,
gdouble progress,
gpointer user_data)
{
GsdLocatePointerData *data = (GsdLocatePointerData *) user_data;
GdkScreen *screen;
GdkDeviceManager *device_manager;
gint cursor_x, cursor_y;
if (gtk_widget_is_composited (data->widget))
{
gdk_window_invalidate_rect (data->window, NULL, FALSE);
data->progress = progress;
}
else if (progress >= data->progress + CIRCLES_PROGRESS_INTERVAL)
{
/* only invalidate window each circle interval */
update_shape (data);
gdk_window_invalidate_rect (data->window, NULL, FALSE);
data->progress += CIRCLES_PROGRESS_INTERVAL;
}
screen = gdk_window_get_screen (data->window);
device_manager = gdk_display_get_device_manager (gdk_window_get_display (data->window));
gdk_window_get_device_position (gdk_screen_get_root_window (screen),
gdk_device_manager_get_client_pointer (device_manager),
&cursor_x, &cursor_y, NULL);
gdk_window_move (data->window,
cursor_x - WINDOW_SIZE / 2,
cursor_y - WINDOW_SIZE / 2);
}
static void
set_transparent_shape (GdkWindow *window)
{
cairo_region_t *region;
region = cairo_region_create ();
gdk_window_shape_combine_region (data->window, region, 0, 0);
cairo_region_destroy (region);
}
static void
unset_transparent_shape (GdkWindow *window)
{
gdk_window_shape_combine_region (data->window, NULL, 0, 0);
}
static void
composited_changed (GtkWidget *widget,
GsdLocatePointerData *data)
{
if (!gtk_widget_is_composited (widget))
set_transparent_shape (data->window);
else
unset_transparent_shape (data->window);
}
static void
timeline_finished_cb (GsdTimeline *timeline,
gpointer user_data)
{
GsdLocatePointerData *data = (GsdLocatePointerData *) user_data;
/* set transparent shape and hide window */
if (!gtk_widget_is_composited (data->widget))
set_transparent_shape (data->window);
gtk_widget_hide (data->widget);
gdk_window_hide (data->window);
}
static void
create_window (GsdLocatePointerData *data,
GdkScreen *screen)
{
GdkVisual *visual;
GdkWindowAttr attributes;
gint attributes_mask;
visual = gdk_screen_get_rgba_visual (screen);
if (visual == NULL)
visual = gdk_screen_get_system_visual (screen);
attributes_mask = GDK_WA_X | GDK_WA_Y;
if (visual != NULL)
attributes_mask = attributes_mask | GDK_WA_VISUAL;
attributes.window_type = GDK_WINDOW_TEMP;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = visual;
attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK;
attributes.width = 1;
attributes.height = 1;
data->window = gdk_window_new (gdk_screen_get_root_window (screen),
&attributes,
attributes_mask);
gdk_window_set_user_data (data->window, data->widget);
}
static GsdLocatePointerData *
gsd_locate_pointer_data_new (GdkScreen *screen)
{
GsdLocatePointerData *data;
data = g_new0 (GsdLocatePointerData, 1);
/* this widget will never be shown, it's
* mainly used to get signals/events from
*/
data->widget = gtk_invisible_new ();
gtk_widget_realize (data->widget);
g_signal_connect (G_OBJECT (data->widget), "draw",
G_CALLBACK (locate_pointer_draw),
data);
data->timeline = gsd_timeline_new (ANIMATION_LENGTH);
g_signal_connect (data->timeline, "frame",
G_CALLBACK (timeline_frame_cb), data);
g_signal_connect (data->timeline, "finished",
G_CALLBACK (timeline_finished_cb), data);
create_window (data, screen);
return data;
}
static void
move_locate_pointer_window (GsdLocatePointerData *data,
GdkScreen *screen)
{
GdkDeviceManager *device_manager;
cairo_region_t *region;
gint cursor_x, cursor_y;
device_manager = gdk_display_get_device_manager (gdk_window_get_display (data->window));
gdk_window_get_device_position (gdk_screen_get_root_window (screen),
gdk_device_manager_get_client_pointer (device_manager),
&cursor_x, &cursor_y, NULL);
gdk_window_move_resize (data->window,
cursor_x - WINDOW_SIZE / 2,
cursor_y - WINDOW_SIZE / 2,
WINDOW_SIZE, WINDOW_SIZE);
/* allow events to happen through the window */
region = cairo_region_create ();
gdk_window_input_shape_combine_region (data->window, region, 0, 0);
cairo_region_destroy (region);
}
void
gsd_locate_pointer (GdkScreen *screen)
{
if (!data)
data = gsd_locate_pointer_data_new (screen);
gsd_timeline_pause (data->timeline);
gsd_timeline_rewind (data->timeline);
/* Create again the window if it is not for the current screen */
if (gdk_screen_get_number (screen) != gdk_screen_get_number (gdk_window_get_screen (data->window)))
{
gdk_window_set_user_data (data->window, NULL);
gdk_window_destroy (data->window);
create_window (data, screen);
}
data->progress = 0.;
g_signal_connect (data->widget, "composited-changed",
G_CALLBACK (composited_changed), data);
move_locate_pointer_window (data, screen);
composited_changed (data->widget, data);
gdk_window_show (data->window);
gtk_widget_show (data->widget);
gsd_timeline_start (data->timeline);
}
#define KEYBOARD_GROUP_SHIFT 13
#define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14))
/* Owen magic */
static GdkFilterReturn
filter (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
{
XEvent *xev = (XEvent *) xevent;
guint keyval;
gint group;
GdkScreen *screen = (GdkScreen *)data;
if (xev->type == ButtonPress)
{
XAllowEvents (xev->xbutton.display,
ReplayPointer,
xev->xbutton.time);
XUngrabButton (xev->xbutton.display,
AnyButton,
AnyModifier,
xev->xbutton.window);
XUngrabKeyboard (xev->xbutton.display,
xev->xbutton.time);
}
if (xev->type == KeyPress || xev->type == KeyRelease)
{
/* get the keysym */
group = (xev->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
xev->xkey.keycode,
xev->xkey.state,
group,
&keyval,
NULL, NULL, NULL);
if (keyval == GDK_KEY_Control_L || keyval == GDK_KEY_Control_R)
{
if (xev->type == KeyPress)
{
XAllowEvents (xev->xkey.display,
SyncKeyboard,
xev->xkey.time);
XGrabButton (xev->xkey.display,
AnyButton,
AnyModifier,
xev->xkey.window,
False,
ButtonPressMask,
GrabModeSync,
GrabModeAsync,
None,
None);
}
else
{
XUngrabButton (xev->xkey.display,
AnyButton,
AnyModifier,
xev->xkey.window);
XAllowEvents (xev->xkey.display,
AsyncKeyboard,
xev->xkey.time);
gsd_locate_pointer (screen);
}
}
else
{
XAllowEvents (xev->xkey.display,
ReplayKeyboard,
xev->xkey.time);
XUngrabButton (xev->xkey.display,
AnyButton,
AnyModifier,
xev->xkey.window);
XUngrabKeyboard (xev->xkey.display,
xev->xkey.time);
}
}
return GDK_FILTER_CONTINUE;
}
static void
set_locate_pointer (void)
{
GdkKeymapKey *keys;
GdkDisplay *display;
GdkScreen *screen;
Window xroot;
int n_keys;
gboolean has_entries;
static const guint keyvals[] = { GDK_KEY_Control_L, GDK_KEY_Control_R };
unsigned i, j;
display = gdk_display_get_default ();
screen = gdk_screen_get_default ();
xroot = gdk_x11_window_get_xid (gdk_screen_get_root_window (screen));
for (j = 0 ; j < G_N_ELEMENTS (keyvals) ; j++)
{
has_entries = gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
keyvals[j],
&keys,
&n_keys);
if (has_entries)
{
for (i = 0; i < n_keys; i++)
{
gdk_x11_display_error_trap_push (display);
XGrabKey (GDK_DISPLAY_XDISPLAY (display),
keys[i].keycode,
0,
xroot,
False,
GrabModeAsync,
GrabModeSync);
XGrabKey (GDK_DISPLAY_XDISPLAY (display),
keys[i].keycode,
LockMask,
xroot,
False,
GrabModeAsync,
GrabModeSync);
XGrabKey (GDK_DISPLAY_XDISPLAY (display),
keys[i].keycode,
Mod2Mask,
xroot,
False,
GrabModeAsync,
GrabModeSync);
XGrabKey (GDK_DISPLAY_XDISPLAY (display),
keys[i].keycode,
Mod4Mask,
xroot,
False,
GrabModeAsync,
GrabModeSync);
gdk_x11_display_error_trap_pop_ignored (display);
}
g_free (keys);
gdk_window_add_filter (gdk_screen_get_root_window (screen),
filter,
screen);
}
}
}
int
main (int argc, char *argv[])
{
gdk_disable_multidevice ();
gtk_init (&argc, &argv);
set_locate_pointer ();
gtk_main ();
return 0;
}
/*
* Copyright © 2001 Jonathan Blandford <jrb@gnome.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* Authors: Jonathan Blandford
*/
#ifndef LOCATE_POINTER_H
#define LOCATE_POINTER_H
#include <gdk/gdk.h>
void gsd_locate_pointer (GdkScreen *screen);
#endif
......@@ -38,7 +38,6 @@
#define GSETTINGS_TOUCHPAD_SCHEMA "org.gnome.desktop.peripherals.touchpad"
/* Mouse settings */
#define KEY_LOCATE_POINTER "locate-pointer"
#define KEY_DWELL_CLICK_ENABLED "dwell-click-enabled"
#define KEY_SECONDARY_CLICK_ENABLED "secondary-click-enabled"
......@@ -52,8 +51,6 @@ struct _GsdMouseManager
GSettings *mouse_settings;
GSettings *gsd_mouse_settings;
gboolean mousetweaks_daemon_running;
gboolean locate_pointer_spawned;
GPid locate_pointer_pid;
};
static void gsd_mouse_manager_class_init (GsdMouseManagerClass *klass);
......@@ -74,38 +71,6 @@ gsd_mouse_manager_class_init (GsdMouseManagerClass *klass)
object_class->finalize = gsd_mouse_manager_finalize;
}
static void
set_locate_pointer (GsdMouseManager *manager,
gboolean state)
{
if (state) {
GError *error = NULL;
char *args[2];
if (manager->locate_pointer_spawned)
return;
args[0] = LIBEXECDIR "/gsd-locate-pointer";
args[1] = NULL;
g_spawn_async (NULL, args, NULL,
0, NULL, NULL,
&manager->locate_pointer_pid, &error);
manager->locate_pointer_spawned = (error == NULL);
if (error) {
g_settings_set_boolean (manager->gsd_mouse_settings, KEY_LOCATE_POINTER, FALSE);
g_error_free (error);
}
} else if (manager->locate_pointer_spawned) {
kill (manager->locate_pointer_pid, SIGHUP);
g_spawn_close_pid (manager->locate_pointer_pid);
manager->locate_pointer_spawned = FALSE;
}
}
static void
set_mousetweaks_daemon (GsdMouseManager *manager,
gboolean dwell_click_enabled,
......@@ -151,8 +116,6 @@ mouse_callback (GSettings *settings,
set_mousetweaks_daemon (manager,
g_settings_get_boolean (settings, KEY_DWELL_CLICK_ENABLED),
g_settings_get_boolean (settings, KEY_SECONDARY_CLICK_ENABLED));
} else if (g_str_equal (key, KEY_LOCATE_POINTER)) {
set_locate_pointer (manager, g_settings_get_boolean (settings, KEY_LOCATE_POINTER));
}
}
......@@ -179,7 +142,6 @@ gsd_mouse_manager_idle_cb (GsdMouseManager *manager)
G_CALLBACK (mouse_callback), manager);
#endif
set_locate_pointer (manager, g_settings_get_boolean (manager->gsd_mouse_settings, KEY_LOCATE_POINTER));
set_mousetweaks_daemon (manager,
g_settings_get_boolean (manager->mouse_a11y_settings, KEY_DWELL_CLICK_ENABLED),
g_settings_get_boolean (manager->mouse_a11y_settings, KEY_SECONDARY_CLICK_ENABLED));
......@@ -224,8 +186,6 @@ gsd_mouse_manager_stop (GsdMouseManager *manager)
g_clear_object (&manager->mouse_settings);
g_clear_object (&manager->touchpad_settings);
g_clear_object (&manager->gsd_mouse_settings);
set_locate_pointer (manager, FALSE);
}
static void
......
This diff is collapsed.
/* gsdtimeline.c
*
* Copyright (C) 2008 Carlos Garnacho <carlos@imendio.com>
*
* 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 2 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/>.
*/
#ifndef __GSD_TIMELINE_H__
#define __GSD_TIMELINE_H__
#include <glib-object.h>
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GSD_TYPE_TIMELINE_DIRECTION (gsd_timeline_direction_get_type ())
#define GSD_TYPE_TIMELINE_PROGRESS_TYPE (gsd_timeline_progress_type_get_type ())
#define GSD_TYPE_TIMELINE (gsd_timeline_get_type ())
typedef enum {
GSD_TIMELINE_DIRECTION_FORWARD,
GSD_TIMELINE_DIRECTION_BACKWARD
} GsdTimelineDirection;