summaryrefslogtreecommitdiff
path: root/plugins/mouse/gsd-locate-pointer.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/mouse/gsd-locate-pointer.c')
-rw-r--r--plugins/mouse/gsd-locate-pointer.c512
1 files changed, 0 insertions, 512 deletions
diff --git a/plugins/mouse/gsd-locate-pointer.c b/plugins/mouse/gsd-locate-pointer.c
deleted file mode 100644
index 7f8cd339..00000000
--- a/plugins/mouse/gsd-locate-pointer.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/* 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;
-}
-