diff options
Diffstat (limited to 'plugins/mouse/gsd-locate-pointer.c')
-rw-r--r-- | plugins/mouse/gsd-locate-pointer.c | 512 |
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; -} - |