summaryrefslogtreecommitdiff
path: root/gui/modules/keymouselistener.c
diff options
context:
space:
mode:
Diffstat (limited to 'gui/modules/keymouselistener.c')
-rw-r--r--gui/modules/keymouselistener.c1010
1 files changed, 0 insertions, 1010 deletions
diff --git a/gui/modules/keymouselistener.c b/gui/modules/keymouselistener.c
deleted file mode 100644
index 759034df..00000000
--- a/gui/modules/keymouselistener.c
+++ /dev/null
@@ -1,1010 +0,0 @@
-/* GDM - The Gnome Display Manager
- * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net>
- *
- * This file Copyright (c) 2003 Sun Microsystems Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <syslog.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/keysym.h>
-
-#include <glib.h>
-#include <gmodule.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#ifdef HAVE_XINPUT
-#include <X11/extensions/XInput.h>
-#endif
-
-/*
- * Note that CONFIGFILE will have to be moved to somewhere more generic
- * if this module is ever moved outside of gdm.
- */
-#define CONFIGFILE GDMCONFDIR "/modules/AccessKeyMouseEvents"
-#define iseol(ch) ((ch) == '\r' || (ch) == '\f' || (ch) == '\0' || \
- (ch) == '\n')
-
-#define N_INPUT_TYPES 40
-
-typedef enum
-{
- GESTURE_TYPE_KEY = 1 << 0,
- GESTURE_TYPE_MOUSE = 1 << 1,
- GESTURE_TYPE_BUTTON = 1 << 2
-} GestureType;
-
-typedef enum {
- XINPUT_TYPE_MOTION = 0,
- XINPUT_TYPE_BUTTON_PRESS = 1,
- XINPUT_TYPE_BUTTON_RELEASE = 2,
- XINPUT_TYPE_KEY_PRESS = 3,
- XINPUT_TYPE_KEY_RELEASE = 4
-} XInputEventType;
-
-typedef struct {
- guint keysym;
- GdkModifierType state;
- guint keycode;
-} Key;
-
-typedef struct {
- guint number;
- GdkModifierType state;
-} Button;
-
-union Input {
- Key key;
- Button button;
-};
-
-typedef struct {
- GestureType type;
- union Input input;
- char *gesture_str;
- GSList *actions;
- guint n_times;
- guint duration;
- guint timeout;
- gint start_time;
- gint seq_count;
-} Gesture;
-
-static int xinput_types[N_INPUT_TYPES];
-
-extern char **environ;
-
-static gboolean debug_gestures = FALSE;
-static GSList *gesture_list = NULL;
-static int lineno = 0;
-
-static gchar * screen_exec_display_string (GdkScreen *screen, const char *old);
-static void create_event_watcher (void);
-static void load_gestures(gchar *path);
-static gchar ** get_exec_environment (XEvent *xevent);
-static Gesture * parse_line(gchar *buf);
-static GdkFilterReturn gestures_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data);
-static gint is_mouseX (const gchar *string);
-static gint is_switchX (const gchar *string);
-
-#define gesture_list_get_matches(a, b, c) (g_slist_find_custom (a, b, c))
-
-static void
-free_gesture (Gesture *gesture)
-{
- if (gesture == NULL)
- return;
-
- g_slist_foreach (gesture->actions, (GFunc)g_free, NULL);
- g_slist_free (gesture->actions);
- g_free (gesture->gesture_str);
- g_free (gesture);
-}
-
-static gchar *
-screen_exec_display_string (GdkScreen *screen, const char *old)
-{
- GString *str;
- const gchar *old_display;
- gchar *retval;
- gchar *p;
-
- g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
-
- old_display = gdk_display_get_name (gdk_screen_get_display (screen));
-
- str = g_string_new ("DISPLAY=");
- g_string_append (str, old_display);
-
- p = strrchr (str->str, '.');
- if (p && p > strchr (str->str, ':'))
- g_string_truncate (str, p - str->str);
-
- g_string_append_printf (str, ".%d", gdk_screen_get_number (screen));
-
- retval = str->str;
-
- g_string_free (str, FALSE);
-
- return retval;
-}
-
-static void
-init_xinput (GdkDisplay *display, GdkWindow *root)
-{
-#ifdef HAVE_XINPUT
- XEventClass event_list[40];
- int i, j, number = 0, num_devices;
- XDeviceInfo *devices = NULL;
- XDevice *device = NULL;
-
- devices = XListInputDevices (GDK_DISPLAY_XDISPLAY (display),
- &num_devices);
-
- if (debug_gestures)
- syslog (LOG_WARNING, "checking %d input devices...", num_devices);
-
- for (i=0; i < num_devices; i++) {
- if (devices[i].use == IsXExtensionDevice)
- {
- device = XOpenDevice (GDK_DISPLAY_XDISPLAY (display),
- devices[i].id);
-
- for (j=0; j < device->num_classes && number < 39; j++) {
-
- switch (device->classes[j].input_class)
- {
- case KeyClass:
- DeviceKeyPress (device,
- xinput_types[XINPUT_TYPE_KEY_PRESS],
- event_list[number]);
- number++;
- DeviceKeyRelease (device,
- xinput_types[XINPUT_TYPE_KEY_RELEASE],
- event_list[number]);
- number++;
- break;
- case ButtonClass:
- DeviceButtonPress (device,
- xinput_types[XINPUT_TYPE_BUTTON_PRESS],
- event_list[number]);
- number++;
- DeviceButtonRelease (device,
- xinput_types[XINPUT_TYPE_BUTTON_RELEASE],
- event_list[number]);
- number++;
- break;
- case ValuatorClass:
- DeviceMotionNotify (device,
- xinput_types[XINPUT_TYPE_MOTION],
- event_list[number]);
- number++;
- }
- }
- }
- }
-
- if (debug_gestures)
- syslog (LOG_WARNING, "%d event types available", number);
-
- if (XSelectExtensionEvent(GDK_WINDOW_XDISPLAY (root),
- GDK_WINDOW_XWINDOW (root),
- event_list, number)) {
- if (debug_gestures)
- syslog (LOG_WARNING,
- "Can't select input device events!");
- }
-#endif
-}
-
-static void create_event_watcher (void)
-{
- GdkDisplay *display;
-
- display = gdk_display_get_default();
- if (!display)
- return;
-
- load_gestures(CONFIGFILE);
-
- init_xinput (display, gdk_screen_get_root_window (
- gdk_display_get_default_screen (display)));
-
- gdk_window_add_filter (NULL, gestures_filter, NULL);
-
- return;
-}
-
-
-static void
-load_gestures(gchar *path)
-{
- FILE *fp;
- Gesture *tmp_gesture;
- gchar buf[1024];
-
- fp = fopen (path, "r");
- if (fp == NULL) {
- /* TODO - I18n */
- if (debug_gestures)
- syslog (LOG_WARNING, _("Cannot open gestures file: %s"),
- path);
- return;
- }
-
- while (fgets (buf, sizeof (buf), fp) != NULL) {
-
- tmp_gesture = (Gesture *)parse_line(buf);
- if (tmp_gesture) {
-
- /* Is the key already associated with an existing
- gesture? */
- if (strcmp (tmp_gesture->gesture_str, "<Add>") == 0) {
-
- /* Add another action to the last gesture */
- Gesture *last_gesture;
- GSList *last_item = g_slist_last (gesture_list);
-
- /* If there is no last_item to add onto ignore
- the entry */
- if (last_item) {
- last_gesture = (Gesture *)
- last_item->data;
-
- /* Add the action to the last gesture's
- actions list */
- last_gesture->actions =
- g_slist_append (last_gesture->actions,
- g_strdup ((gchar *)tmp_gesture->actions->data));
- }
- free_gesture (tmp_gesture);
-
- /* We must be able to deal with multiple
- unambiguous gestures attached to one
- switch/button */
- } else {
- gesture_list = g_slist_append (gesture_list,
- tmp_gesture);
- }
- }
- }
- fclose (fp);
-}
-
-
-/**
- * get_exec_environment:
- *
- * Description: Modifies the current program environment to
- * ensure that $DISPLAY is set such that a launched application
- * inheriting this environment would appear on screen.
- *
- * Returns: a newly-allocated %NULL-terminated array of strings or
- * %NULL on error. Use g_strfreev() to free it.
- *
- * mainly ripped from egg_screen_exec_display_string in
- * gnome-panel/egg-screen-exec.c
- **/
-static gchar **
-get_exec_environment (XEvent *xevent)
-{
- gchar **retval = NULL;
- gint i;
- gint display_index = -1;
-
- GdkScreen *screen = NULL;
- GdkWindow *window = gdk_xid_table_lookup (xevent->xkey.root);
-
- if (window)
- screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
-
- /* TODO: revisit this fallback, it's suspect since Xi events might not
- have xkey.root set */
-
- else
- screen = gdk_display_get_default_screen (gdk_display_get_default ());
-
- g_assert (GDK_IS_SCREEN (screen));
-
- for (i=0; environ [i]; i++)
- if (!strncmp (environ [i], "DISPLAY", 7))
- display_index = i;
-
- if (display_index == -1)
- display_index = i++;
-
- retval = g_new0 (char *, i + 1);
-
- for (i=0; environ [i]; i++) {
- if (i == display_index)
- retval [i] = screen_exec_display_string (screen,
- environ[i]);
- else
- retval [i] = g_strdup (environ [i]);
- }
-
- retval [i] = NULL;
-
- return retval;
-}
-
-static Gesture *
-parse_line (gchar *buf)
-{
- static GdkDisplay *display = NULL;
- Gesture *tmp_gesture = NULL;
- gchar *keystring;
- gchar *keyservice;
- gint button = 0;
-
- if (!display) {
- if ((display = gdk_display_get_default()) == NULL)
- return NULL;
- }
- lineno++;
-
- if ((*buf == '#') || (iseol(*buf)) || (buf == NULL))
- return NULL;
-
- /* Find the key name */
- keystring = strtok (buf, " \t\n\r\f");
- if (keystring == NULL) {
- /* TODO - Error messages */
- return NULL;
- }
-
- tmp_gesture = g_new0 (Gesture, 1);
- tmp_gesture->gesture_str = g_strdup (keystring);
-
- if (strcmp (tmp_gesture->gesture_str, "<Add>") != 0) {
- guint n, duration, timeout;
- gchar *tmp_string;
-
- tmp_gesture->start_time = 0;
- tmp_gesture->seq_count = 0;
-
- button = is_mouseX (tmp_gesture->gesture_str);
- if (button > 0) {
- tmp_gesture->type = GESTURE_TYPE_MOUSE;
- tmp_gesture->input.button.number = button;
- } else if ((button = is_switchX (tmp_gesture->gesture_str)) == TRUE) {
- tmp_gesture->type = GESTURE_TYPE_BUTTON;
- tmp_gesture->input.button.number = button;
- } else {
- tmp_gesture->type = GESTURE_TYPE_KEY;
- gtk_accelerator_parse (tmp_gesture->gesture_str,
- &(tmp_gesture->input.key.keysym),
- &(tmp_gesture->input.key.state));
- if (tmp_gesture->input.key.keysym == 0 &&
- tmp_gesture->input.key.state == 0) {
- /* TODO - Error messages here */
- free_gesture (tmp_gesture);
- return NULL;
- }
- tmp_gesture->input.key.keycode =
- XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display),
- tmp_gesture->input.key.keysym);
- }
-
- if (tmp_gesture->type == 0) {
- /* TODO - Error messages here */
- free_gesture (tmp_gesture);
- return NULL;
- }
- /* [TODO] Need to clean up here. */
-
- /* Find the repetition number */
- tmp_string = strtok (NULL, " \t\n\r\f");
- if (tmp_string == NULL) {
- /* TODO - Error messages */
- free_gesture (tmp_gesture);
- return NULL;
- }
-
- /* TODO - the above doesn't check for the string to
- be all digits */
- if ((n=atoi (tmp_string)) <= 0) {
- /* Add an error message */
- free_gesture (tmp_gesture);
- return NULL;
- }
- tmp_gesture->n_times = n;
-
- /*
- * Find the key press duration (in ms)
- */
- tmp_string = strtok (NULL, " \t\n\r\f");
- if (tmp_string == NULL) {
- /* TODO - Error messages */
- free_gesture (tmp_gesture);
- return NULL;
- }
- /* TODO - the above doesn't check for the string to
- be all digits */
-
- duration = atoi (tmp_string);
- if (duration < 0) {
- /* Add an error message */
- free_gesture (tmp_gesture);
- return NULL;
- }
- tmp_gesture->duration = duration;
-
- /*
- * Find the timeout duration (in ms). Timeout value is the
- * time within which consecutive keypress actions must be
- * performed by the user before the sequence is discarded.
- */
- tmp_string = strtok (NULL, " \t\n\r\f");
- if (tmp_string == NULL) {
- /* TODO - Error messages */
- free_gesture (tmp_gesture);
- return NULL;
- }
-
- /*
- * A gesture with an n_times value greater than 1 and a
- * non-positive timeout can never be triggered, so do not
- * accept such gestures. The value of timeout is not used
- * if n_times is 1, so don't bother setting the timeout in
- * this case.
- */
- tmp_gesture->timeout = 0;
- if (tmp_gesture->n_times > 1) {
- if ((timeout=atoi (tmp_string)) <= 0) {
- /* Add an error message */;
- free_gesture (tmp_gesture);
- return NULL;
- }
- tmp_gesture->timeout = timeout;
- }
- }
-
- /*
- * Find service. Permit blank space so arguments can be supplied.
- */
- keyservice = strtok (NULL, "\n\r\f");
- if (keyservice == NULL) {
- /* TODO - Error messages */
- free_gesture (tmp_gesture);
- return NULL;
- }
- /* skip over initial whitespace */
- while (*keyservice && isspace (*keyservice))
- keyservice++;
-
- tmp_gesture->actions = g_slist_append(tmp_gesture->actions,
- g_strdup(keyservice));
-
- if (debug_gestures)
- syslog (LOG_WARNING, "gesture parsed for %s button %d",
- (tmp_gesture->type == GESTURE_TYPE_MOUSE) ? "mouse" :
- ((tmp_gesture->type == GESTURE_TYPE_BUTTON) ? "switch" :
- "key"), tmp_gesture->input.button.number);
-
- return tmp_gesture;
-}
-
-/*
- * These modifiers are ignored because they make no sense.
- * .eg <NumLock>x
- *
- * FIXME: [sadly, NumLock isn't always mapped to the same modifier, so the logic
- * below is faulty - bill]
- */
-#define IGNORED_MODS (GDK_LOCK_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK)
-#define USED_MODS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK | \
- GDK_MOD4_MASK | GDK_MOD5_MASK)
-
-static gboolean
-change_cursor_back (gpointer data)
-{
- GdkCursor *cursor = gdk_cursor_new (GDK_LEFT_PTR);
- gdk_window_set_cursor (gdk_get_default_root_window (), cursor);
- gdk_cursor_unref (cursor);
-
- return FALSE;
-}
-
-static gint
-event_time (XEvent *ev)
-{
- if ((ev->type == KeyPress) ||
- (ev->type == KeyRelease))
- return ((XKeyEvent *) ev)->time;
- else if ((ev->type == ButtonPress) ||
- (ev->type == ButtonRelease))
- return ((XButtonEvent *) ev)->time;
- else if ((ev->type == xinput_types[XINPUT_TYPE_KEY_PRESS]) ||
- (ev->type == xinput_types[XINPUT_TYPE_KEY_RELEASE]))
- return ((XDeviceKeyEvent *) ev)->time;
- else if ((ev->type == xinput_types[XINPUT_TYPE_BUTTON_PRESS]) ||
- (ev->type == xinput_types[XINPUT_TYPE_BUTTON_RELEASE]))
- return ((XDeviceButtonEvent *) ev)->time;
- else
- return 0;
-}
-
-static gint
-elapsed_time (XEvent *ev1, XEvent *ev2)
-{
- return event_time (ev2) - event_time (ev1);
-}
-
-static gboolean
-keycodes_equal (XEvent *ev1, XEvent *ev2)
-{
- if (ev1->type == ev2->type)
- {
- if (ev1->type == KeyPress || ev1->type == KeyRelease)
- {
- return (((XKeyEvent *) ev1)->keycode == ((XKeyEvent *) ev2)->keycode);
- }
- else if (ev1->type == xinput_types[XINPUT_TYPE_KEY_PRESS] ||
- ev1->type == xinput_types[XINPUT_TYPE_KEY_RELEASE])
- {
- return (((XDeviceKeyEvent *) ev1)->keycode == ((XDeviceKeyEvent *) ev2)->keycode);
- }
- }
- return FALSE;
-}
-
-static gint
-key_gesture_compare_func (gconstpointer a, gconstpointer b)
-{
- const Gesture *gesture = a;
- const XEvent *xev = b;
-
- if (gesture->type == GESTURE_TYPE_KEY)
- {
- if (((xev->type == KeyPress) || (xev->type == KeyRelease)) &&
- (xev->xkey.keycode == gesture->input.key.keycode) &&
- ((xev->xkey.state & USED_MODS) == gesture->input.key.state))
- return 0;
- else if (((xev->type == xinput_types[XINPUT_TYPE_KEY_PRESS]) ||
- (xev->type == xinput_types[XINPUT_TYPE_KEY_RELEASE])) &&
- (xev->xkey.keycode == gesture->input.key.keycode) &&
- ((xev->xkey.state & USED_MODS) == gesture->input.key.state))
- return 0;
- else
- return 1;
- }
- else if ((gesture->type == GESTURE_TYPE_MOUSE) &&
- ((xev->type == ButtonPress) || (xev->type == ButtonRelease)) &&
- (xev->xbutton.button == gesture->input.button.number))
- return 0;
- else if ((gesture->type == GESTURE_TYPE_BUTTON) &&
- ((xev->type == xinput_types[XINPUT_TYPE_BUTTON_PRESS]) ||
- (xev->type == xinput_types[XINPUT_TYPE_BUTTON_RELEASE])) &&
- ((XDeviceButtonEvent *) xev)->button == gesture->input.button.number)
- return 0;
- else
- return 1;
-}
-
-#define event_is_gesture_type(xevent) (xevent->type == KeyPress ||\
- xevent->type == KeyRelease ||\
- xevent->type == ButtonPress ||\
- xevent->type == ButtonRelease ||\
- xevent->type == xinput_types[XINPUT_TYPE_KEY_PRESS] ||\
- xevent->type == xinput_types[XINPUT_TYPE_KEY_RELEASE] ||\
- xevent->type == xinput_types[XINPUT_TYPE_BUTTON_PRESS] ||\
- xevent->type == xinput_types[XINPUT_TYPE_BUTTON_RELEASE])
-
-static GdkFilterReturn
-gestures_filter (GdkXEvent *gdk_xevent,
- GdkEvent *event,
- gpointer data)
-{
- XEvent *xevent = (XEvent *)gdk_xevent;
- GSList *li, *act_li;
- Gesture *curr_gesture = NULL;
- XID xinput_device = None;
-
- static XEvent *last_event = NULL;
- static gint seq_count = 0;
-
- if (!event_is_gesture_type (xevent))
- return GDK_FILTER_CONTINUE;
-
- if (!last_event)
- last_event = g_new0(XEvent, 1);
-
- if ((xevent->type == KeyPress) ||
- (xevent->type == xinput_types[XINPUT_TYPE_KEY_PRESS]))
- {
-
- if (debug_gestures)
- syslog (LOG_WARNING, "key press");
-
- if (last_event->type == KeyPress &&
- last_event->xkey.keycode == xevent->xkey.keycode) {
- /* these come from auto key-repeat */
-
- if (debug_gestures)
- syslog (LOG_WARNING, "rejecting repeat");
-
- return GDK_FILTER_CONTINUE;
- }
-
- if (seq_count > 0 &&
- last_event->type != KeyRelease) {
-
- if (debug_gestures)
- syslog (LOG_WARNING,
- "last event wasn't a release, resetting seq");
- seq_count = 0;
- }
- else if (seq_count > 0 &&
- keycodes_equal (last_event, xevent)) {
-
- if (debug_gestures)
- syslog (LOG_WARNING,
- "keycode doesn't match last event, resetting seq");
- seq_count = 0;
- }
-
- /* Find the associated gesture for this keycode & state */
- li = gesture_list_get_matches (gesture_list, xevent,
- key_gesture_compare_func);
-
- if (li) {
- curr_gesture = li->data;
- if (debug_gestures)
- syslog (LOG_WARNING,
- "found a press match [%s]",
- curr_gesture->gesture_str);
-
- /* xevent time values are in milliseconds. */
- /* The config file spec is in ms */
- if (curr_gesture->timeout > 0 && seq_count > 0 &&
- elapsed_time (last_event, xevent) >
- curr_gesture->timeout) {
-
- if (debug_gestures)
- syslog (LOG_WARNING,
- "timeout exceeded: reset seq and gesture");
-
- /* The timeout has been exceeded.
- Reset the sequence. */
- seq_count = 0;
- curr_gesture = NULL;
- }
- }
- }
- else if ((xevent->type == KeyRelease) ||
- (xevent->type == xinput_types[XINPUT_TYPE_KEY_RELEASE]))
- {
- if (debug_gestures)
- syslog (LOG_WARNING, "key release");
-
- if (seq_count > 0 &&
- ((last_event->type != KeyPress &&
- last_event->type != xinput_types[XINPUT_TYPE_KEY_PRESS]) ||
- ! keycodes_equal (last_event, xevent))) {
-
- if (debug_gestures)
- syslog (LOG_WARNING,
- "either last event not a keypress, or keycodes don't match. Resetting seq.");
-
- seq_count = 0;
- }
-
- /*
- * Find the associated gesture for this keycode & state
- *
- * Note that here we check the state against the last_event,
- * otherwise key gestures based on modifier keys such as
- * Control_R won't work.
- */
- li = gesture_list_get_matches (gesture_list, xevent,
- key_gesture_compare_func);
-
- if (li) {
- curr_gesture = li->data;
-
- if (debug_gestures)
- syslog (LOG_WARNING, "found a release match [%s]",
- curr_gesture->gesture_str);
-
- if ((curr_gesture->duration > 0) &&
- (elapsed_time (last_event, xevent) < curr_gesture->duration)) {
-
- seq_count = 0;
- curr_gesture = NULL;
-
- if (debug_gestures)
- syslog (LOG_WARNING, "setting current gesture to NULL");
- } else {
- seq_count++;
-
- if (debug_gestures)
- syslog (LOG_WARNING, "incrementing seq_count");
- }
- }
- }
- else if ((xevent->type == ButtonPress) ||
- (xevent->type == xinput_types[XINPUT_TYPE_BUTTON_PRESS])) {
- gint button = 0;
- gint time = 0;
-
- if (xevent->type == ButtonPress) {
- button = xevent->xbutton.button;
- time = xevent->xbutton.time;
-
- if (debug_gestures)
- syslog (LOG_WARNING, "button press: %d", button);
-
- if (seq_count > 0 && (last_event->type != ButtonRelease))
- seq_count = 0;
- else if (seq_count > 0 && last_event->xbutton.button != button) {
- seq_count = 0;
- }
- }
-#ifdef HAVE_XINPUT
- else {
- button = ((XDeviceButtonEvent *) xevent)->button;
- time = ((XDeviceButtonEvent *) xevent)->time;
- if (debug_gestures)
- syslog (LOG_WARNING, "xinput button press: %d", button);
- if (seq_count > 0 &&
- last_event->type != xinput_types[XINPUT_TYPE_BUTTON_RELEASE]) {
- seq_count = 0;
- }
- else if (seq_count > 0 &&
- ((XDeviceButtonEvent *) last_event)->button != button) {
- seq_count = 0;
- }
- }
-#endif
-
- /*
- * Find the associated gesture for this button.
- */
- li = gesture_list_get_matches (gesture_list, xevent,
- key_gesture_compare_func);
- if (li) {
- if (debug_gestures)
- syslog (LOG_WARNING, "found match for press");
-
- curr_gesture = li->data;
-
- if (curr_gesture->timeout > 0 && seq_count > 0) {
-
- /* xevent time values are in milliseconds. */
- /* The config file spec is in ms */
- if (elapsed_time (last_event, xevent) > curr_gesture->timeout) {
-
- /* Timeout has elapsed. Reset the sequence. */
- seq_count = 0;
- curr_gesture = NULL;
-
- if (debug_gestures)
- syslog (LOG_WARNING, "gesture timed out.");
- }
- }
- }
- else if (debug_gestures)
- syslog (LOG_WARNING, "no match for press %d", button);
- }
- else if ((xevent->type == ButtonRelease) ||
- (xevent->type == xinput_types[XINPUT_TYPE_BUTTON_RELEASE]))
- {
- gint button = 0;
- gint time = 0;
-
- if (xevent->type == ButtonRelease)
- {
- button = xevent->xbutton.button;
- time = xevent->xbutton.time;
- if (seq_count > 0 &&
- (last_event->type != ButtonPress ||
- last_event->xbutton.button != button)) {
- if (debug_gestures)
- syslog (LOG_WARNING,
- "resetting count to zero, based on failure to match last event.");
- seq_count = 0;
- }
- }
-#ifdef HAVE_XINPUT
- else
- {
- button = ((XDeviceButtonEvent *)(xevent))->button;
- time = ((XDeviceButtonEvent *)(xevent))->time;
- xinput_device = ((XDeviceButtonEvent *)(xevent))->deviceid;
-
- if (seq_count > 0 &&
- (last_event->type != xinput_types[XINPUT_TYPE_BUTTON_PRESS] ||
- ((XDeviceButtonEvent *) last_event)->button != button)) {
-
- if (debug_gestures)
- syslog (LOG_WARNING,
- "resetting count to zero, based on failure to match last input event.");
-
- seq_count = 0;
- }
- }
-#endif
-
- li = gesture_list_get_matches (gesture_list, xevent,
- key_gesture_compare_func);
-
- if (li) {
- if (debug_gestures)
- syslog (LOG_WARNING, "found match for release");
- curr_gesture = li->data;
- if ((curr_gesture->duration > 0) &&
- (elapsed_time (last_event, xevent) < curr_gesture->duration)) {
- seq_count = 0;
- curr_gesture = NULL;
- if (debug_gestures)
- syslog (LOG_WARNING, "insufficient duration.");
- } else {
- if (debug_gestures)
- syslog (LOG_WARNING, "duration OK");
- seq_count++;
- }
- }
- else if (debug_gestures)
- syslog (LOG_WARNING, "no match for release - button %d",
- button);
- }
-
- /*
- * Did this event complete any gesture sequences?
- */
- last_event = memcpy (last_event, xevent, sizeof(XEvent));
- if (curr_gesture) {
- if (seq_count != curr_gesture->n_times) {
-
- if (debug_gestures)
- syslog (LOG_WARNING,
- "waiting for %d more repetitions...",
- curr_gesture->n_times - seq_count);
-
- return GDK_FILTER_CONTINUE;
- } else {
- gboolean retval;
- gchar **argv = NULL;
- gchar **envp = NULL;
-
- if (debug_gestures)
- syslog (LOG_WARNING, "gesture complete!");
-
- seq_count = 0;
- for (act_li = curr_gesture->actions;
- act_li != NULL; act_li = act_li->next) {
-
- gchar *action = (gchar *)act_li->data;
- g_return_val_if_fail (action != NULL, GDK_FILTER_CONTINUE);
- if (!g_shell_parse_argv (action, NULL, &argv, NULL))
- continue;
-
- envp = get_exec_environment (xevent);
-
- if (debug_gestures)
- syslog (LOG_WARNING, "Action is %s", action);
-
- retval = g_spawn_async (NULL,
- argv,
- envp,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- NULL,
- NULL);
-
- g_strfreev (argv);
- g_strfreev (envp);
-
- if ( ! retval) {
- GtkWidget *dialog =
- gtk_message_dialog_new (NULL, 0,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("Error while trying to run (%s)\n"\
- "which is linked to (%s)"),
- action,
- curr_gesture->gesture_str);
- gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
- FALSE);
- g_signal_connect (dialog, "response",
- G_CALLBACK (gtk_widget_destroy),
- NULL);
- gtk_widget_show (dialog);
- } else {
- GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
- gdk_window_set_cursor (gdk_get_default_root_window (),
- cursor);
- gdk_cursor_unref (cursor);
- g_timeout_add (2000,
- change_cursor_back,
- NULL);
- }
- }
- return GDK_FILTER_CONTINUE;
- }
- }
- return GDK_FILTER_CONTINUE;
-}
-
-
-static gint
-is_mouseX (const gchar *string)
-{
- if ((string[0] == '<') &&
- (string[1] == 'm' || string[1] == 'M') &&
- (string[2] == 'o' || string[2] == 'O') &&
- (string[3] == 'u' || string[3] == 'U') &&
- (string[4] == 's' || string[4] == 'S') &&
- (string[5] == 'e' || string[5] == 'E') &&
- (isdigit(string[6]) &&
- (atoi(&string[6]) > 0) &&
- (atoi(&string[6]) < 6)) &&
- (string[7] == '>'))
- return atoi(&string[6]);
- else
- return 0;
-}
-
-static gint
-is_switchX (const gchar *string)
-{
- if ((string[0] == '<') &&
- (string[1] == 's' || string[1] == 'S') &&
- (string[2] == 'w' || string[2] == 'W') &&
- (string[3] == 'i' || string[3] == 'I') &&
- (string[4] == 't' || string[4] == 'T') &&
- (string[5] == 'c' || string[5] == 'C') &&
- (string[6] == 'h' || string[6] == 'H') &&
- (isdigit(string[7]) &&
- (atoi(&string[7]) > 0) &&
- (atoi(&string[7]) < 6)) &&
- (string[8] == '>'))
- return atoi(&string[7]);
- else
- return 0;
-}
-
-/* The init function for this gtk module */
-G_MODULE_EXPORT void gtk_module_init(int *argc, char* argv[]);
-
-void gtk_module_init(int *argc, char* argv[])
-{
- if (g_getenv ("GDM_DEBUG_GESTURES") != NULL)
- debug_gestures = TRUE;
-
- if (debug_gestures) {
- /* If not running under GDM, then need to openlog ourselves */
- if (g_getenv ("RUNNING_UNDER_GDM") == NULL)
- openlog ("gesturelistener", LOG_PID, LOG_DAEMON);
-
- syslog (LOG_WARNING, "keymouselistener loaded.");
- }
-
- create_event_watcher ();
-}