summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Cameron <Brian.Cameron@Sun.Com>2005-02-14 22:22:42 +0000
committerBrian Cameron <bcameron@src.gnome.org>2005-02-14 22:22:42 +0000
commitc17679d7b3d3ee59a0f2b732bf09133b17582c2e (patch)
tree96c58c70a396b519deea5f9889569bc3a4ade682
parentb007f1be1ca71a2c094bb50700bc0e87bf70aea5 (diff)
downloadgdm-c17679d7b3d3ee59a0f2b732bf09133b17582c2e.tar.gz
Updated files to also integrate patch for bug #142834.
Thu Feb 14 16:20:00 2005 Brian Cameron <Brian.Cameron@Sun.Com> * acconfig.h, gui/modules/Makefile.am, gui/modules/dwellmouselistener.c, gui/modules/keymouselistener.c: Updated files to also integrate patch for bug #142834.
-rw-r--r--ChangeLog9
-rw-r--r--acconfig.h9
-rw-r--r--gui/modules/Makefile.am4
-rw-r--r--gui/modules/dwellmouselistener.c14
-rw-r--r--gui/modules/keymouselistener.c225
5 files changed, 159 insertions, 102 deletions
diff --git a/ChangeLog b/ChangeLog
index af74f770..5b3f3178 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu Feb 14 16:20:00 2005 Brian Cameron <Brian.Cameron@Sun.Com>
+
+ * acconfig.h, gui/modules/Makefile.am,
+ gui/modules/dwellmouselistener.c,
+ gui/modules/keymouselistener.c: Updated files to
+ also integrate patch for bug #142834.
+
Thu Feb 14 15:10:00 2005 Brian Cameron <Brian.Cameron@Sun.Com>
* configure.in, gui/modules/AccessKeyMouseEvents.in,
@@ -5,7 +12,7 @@ Thu Feb 14 15:10:00 2005 Brian Cameron <Brian.Cameron@Sun.Com>
gui/modules/keymouselistener.c: Update gesture
listeners so that they listen for XInput events. Also
adds better default gestures for gok and gnopernicus.
- Fixes bug 142833.
+ Fixes bug #142833.
Thu Feb 07 21:10:00 2005 Brian Cameron <Brian.Cameron@Sun.Com>
diff --git a/acconfig.h b/acconfig.h
index b8b57326..4002a7ba 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -25,16 +25,17 @@
#undef HAVE_PASSWDEXPIRED
#undef HAVE_SCHED_YIELD
#undef HAVE_SELINUX
+#undef HAVE_SETENV
+#undef HAVE_SETRESUID
#undef HAVE_SHADOW
+#undef HAVE_SOLARIS_XINERAMA
#undef HAVE_STPCPY
#undef HAVE_SYS_SOCKIO_H
#undef HAVE_TCPWRAPPERS
+#undef HAVE_UNSETENV
#undef HAVE_XINERAMA
#undef HAVE_XFREE_XINERAMA
-#undef HAVE_SOLARIS_XINERAMA
-#undef HAVE_SETENV
-#undef HAVE_UNSETENV
-#undef HAVE_SETRESUID
+#undef HAVE_XINPUT
#undef EXPANDED_AUTHDIR
#undef EXPANDED_DATADIR
#undef EXPANDED_BINDIR
diff --git a/gui/modules/Makefile.am b/gui/modules/Makefile.am
index cdd7f351..a117a039 100644
--- a/gui/modules/Makefile.am
+++ b/gui/modules/Makefile.am
@@ -22,7 +22,7 @@ libkeymouselistener_la_LDFLAGS = \
-rpath $(moduledir) -module -avoid-version \
$(GUI_LIBS) \
$(X_LIBS) \
- $(X_EXTRA_LIBS) \
+ $(X_EXTRA_LIBS) \
-L$(top_builddir)/vicious-extensions \
-lviciousui
@@ -33,7 +33,7 @@ libdwellmouselistener_la_LDFLAGS = \
-rpath $(moduledir) -module -avoid-version \
$(GUI_LIBS) \
$(X_LIBS) \
- $(X_EXTRA_LIBS) \
+ $(X_EXTRA_LIBS) \
-L$(top_builddir)/vicious-extensions \
-lviciousui
diff --git a/gui/modules/dwellmouselistener.c b/gui/modules/dwellmouselistener.c
index 10cba22a..0ed59cf6 100644
--- a/gui/modules/dwellmouselistener.c
+++ b/gui/modules/dwellmouselistener.c
@@ -33,11 +33,11 @@
#include <X11/Xlib.h>
#include <config.h>
-
+
#ifdef HAVE_XINPUT
#include <X11/extensions/XInput.h>
#endif
-
+
/*
* Note that CONFIGFILE will have to be changed to something more generic
* if this module is ever moved outside of gdm.
@@ -87,7 +87,6 @@ static GSList *binding_list = NULL;
extern char **environ;
static guint enter_signal_id = 0;
static guint leave_signal_id = 0;
-
static int xinput_type_motion = 0;
static Crossings *crossings = NULL;
@@ -96,7 +95,7 @@ static guint max_crossings = 0;
static XID *ext_input_devices = NULL;
static gint ext_device_count = 0;
static gboolean latch_core_pointer = TRUE;
-
+
static void create_event_watcher ();
static void load_bindings(gchar *path);
static gchar * screen_exec_display_string (GdkScreen *screen, const char *old);
@@ -112,6 +111,7 @@ is_ext_device (XID id)
gint i;
for (i = 0; i < ext_device_count; i++)
if (id == ext_input_devices[i]) return TRUE;
+ g_message ("is-ext-device failed for %d", id);
return FALSE;
}
@@ -667,8 +667,8 @@ leave_enter_emission_hook (GSignalInvocationHint *ihint,
g_timeout_add (2000,
change_cursor_back,
NULL);
- latch_core_pointer = FALSE;
- /* once we've recognized a gesture, we need to leave the pointer alone */
+ latch_core_pointer = FALSE;
+ /* once we've recognized a gesture, we need to leave the pointer alone */
}
}
}
@@ -743,7 +743,7 @@ create_event_watcher (void)
G_MODULE_EXPORT void gtk_module_init (int *argc, char* argv[]);
void gtk_module_init (int *argc, char* argv[])
-{
+{
create_event_watcher ();
}
diff --git a/gui/modules/keymouselistener.c b/gui/modules/keymouselistener.c
index 6660cba5..98ce7c87 100644
--- a/gui/modules/keymouselistener.c
+++ b/gui/modules/keymouselistener.c
@@ -42,33 +42,18 @@
#include <X11/extensions/XInput.h>
#endif
+
/*
* Note that CONFIGFILE will have to be changed to something more generic
* if this module is ever moved outside of gdm.
*/
+#undef DEBUG_GESTURES
+
#define CONFIGFILE EXPANDED_SYSCONFDIR "/gdm/modules/AccessKeyMouseEvents"
#define iseol(ch) ((ch) == '\r' || (ch) == '\f' || (ch) == '\0' || \
(ch) == '\n')
-#ifdef HAVE_XINPUT
-#define XEV_KEYCODE(xev) ((xev->type == KeyPress || xev->type == KeyRelease ) ? xev->xkey.keycode :\
- (xev->type == xinput_types[XINPUT_TYPE_KEY_PRESS] || \
- xev->type == xinput_types[XINPUT_TYPE_KEY_RELEASE]) ?\
- ((XDeviceKeyEvent *)xev)->keycode : -1)
-#else
-#define XEV_KEYCODE(xev) (xev->xkey.keycode)
-#endif
-
-#ifdef HAVE_XINPUT
-#define XEV_STATE(xev) ((xev->type == KeyPress || xev->type == KeyRelease ) ? xev->xkey.state :\
- (xev->type == xinput_types[XINPUT_TYPE_KEY_PRESS] || \
- xev->type == xinput_types[XINPUT_TYPE_KEY_RELEASE]) ?\
- ((XDeviceKeyEvent *)xev)->state : -1)
-#else
-#define XEV_STATE(xev) (xev->xkey.state)
-#endif
-
#define N_INPUT_TYPES 40
typedef enum
@@ -110,6 +95,8 @@ typedef struct {
guint n_times;
guint duration;
guint timeout;
+ gint start_time;
+ gint seq_count;
} Gesture;
static int xinput_types[N_INPUT_TYPES];
@@ -123,11 +110,12 @@ static void create_event_watcher ();
static void load_gestures(gchar *path);
static gchar ** get_exec_environment (XEvent *xevent);
static Gesture * parse_line(gchar *buf);
-static gboolean gesture_already_used (Gesture *gesture);
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)
{
@@ -286,10 +274,8 @@ load_gestures(gchar *path)
}
free_gesture (tmp_gesture);
/* We must be able to deal with multiple unambiguous gestures attached to one switch/button */
- } else if (1) /* ! gesture_already_used (tmp_gesture)) see bug 144048 */
+ } else
gesture_list = g_slist_append (gesture_list, tmp_gesture);
- else
- free_gesture (tmp_gesture);
}
}
fclose(fp);
@@ -379,7 +365,10 @@ parse_line (gchar *buf)
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;
@@ -504,39 +493,12 @@ parse_line (gchar *buf)
/*
* These modifiers are ignored because they make no sense.
- * .eg <NumLock>x
+ * .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_MOD3_MASK | GDK_MOD5_MASK)
+#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_MOD2_MASK | GDK_MOD4_MASK)
-
-#define N_BITS 32
-
-static gboolean
-gesture_already_used (Gesture *gesture)
-{
- GSList *li;
-
- for (li = gesture_list; li != NULL; li = li->next) {
- Gesture *tmp_gesture = (Gesture*) li->data;
-
- if (tmp_gesture != gesture && tmp_gesture->type == gesture->type) {
- switch (tmp_gesture->type) {
- case (GESTURE_TYPE_KEY):
- if (tmp_gesture->input.key.keycode == gesture->input.key.keycode &&
- tmp_gesture->input.key.state == gesture->input.key.state)
- return TRUE;
- case (GESTURE_TYPE_MOUSE):
- if (tmp_gesture->input.button.number == gesture->input.button.number)
- return TRUE;
- default:
- break;
- }
- }
- }
- return FALSE;
-}
+ GDK_MOD4_MASK | GDK_MOD5_MASK)
static gboolean
change_cursor_back (gpointer data)
@@ -549,30 +511,87 @@ change_cursor_back (gpointer data)
}
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) &&
- (XEV_KEYCODE (xev) == gesture->input.key.keycode) &&
- ((XEV_STATE (xev) & USED_MODS) == gesture->input.key.state))
+ 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->type == ButtonPress) || (xev->type == ButtonRelease)) &&
(xev->xbutton.button == gesture->input.button.number))
return 0;
else if ((gesture->type == GESTURE_TYPE_BUTTON) &&
-#ifdef HAVE_XINPUT
- (xev->type == xinput_types [XINPUT_TYPE_BUTTON_PRESS] ||
- xev->type == xinput_types[XINPUT_TYPE_BUTTON_RELEASE]) &&
-#endif
+ ((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,
@@ -586,58 +605,72 @@ gestures_filter (GdkXEvent *gdk_xevent,
static XEvent *last_event = NULL;
static gint seq_count = 0;
- if (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])
- return GDK_FILTER_CONTINUE;
+ 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]))
{
+#ifdef DEBUG_GESTURES
+ g_message ("key press");
+#endif
if (last_event->type == KeyPress &&
last_event->xkey.keycode == xevent->xkey.keycode) {
- /* they comes from auto key-repeat */
+ /* these come from auto key-repeat */
+#ifdef DEBUG_GESTURES
+ g_message ("rejecting repeat");
+#endif
return GDK_FILTER_CONTINUE;
}
- if (seq_count > 0 &&
- (xevent->type == KeyPress &&
- last_event->type != KeyRelease)) {
+ if (seq_count > 0 &&
+ last_event->type != KeyRelease) {
+#ifdef DEBUG_GESTURES
+ g_message ("last event wasn't a release, resetting seq");
+#endif
seq_count = 0;
}
else if (seq_count > 0 &&
- xevent->type == KeyPress &&
- last_event->xkey.keycode != xevent->xkey.keycode) {
+ keycodes_equal (last_event, xevent)) {
+#ifdef DEBUG_GESTURES
+ g_message ("keycode doesn't match last event, resetting seq");
+#endif
seq_count = 0;
}
/*
* Find the associated gesture for this keycode & state
*/
- li = g_slist_find_custom (gesture_list, xevent, key_gesture_compare_func);
+ li = gesture_list_get_matches (gesture_list, xevent, key_gesture_compare_func);
if (li) {
curr_gesture = li->data;
+#ifdef DEBUG_GESTURES
+ g_message ("found a press match [%s]", curr_gesture->gesture_str);
+#endif
if (curr_gesture->timeout > 0 && seq_count > 0 &&
/* xevent time values are in milliseconds. The config file spec is in ms */
- (xevent->xkey.time - last_event->xkey.time) > curr_gesture->timeout) {
+ elapsed_time (last_event, xevent) > curr_gesture->timeout) {
+#ifdef DEBUG_GESTURES
+ g_message ("timeout exceeded: reset seq and gesture");
+#endif
seq_count = 0; /* The timeout has been exceeded. Reset the sequence. */
-
curr_gesture = NULL;
}
}
}
else if ((xevent->type == KeyRelease) || (xevent->type == xinput_types[XINPUT_TYPE_KEY_RELEASE]))
{
+#ifdef DEBUG_GESTURES
+ g_message ("key release");
+#endif
if (seq_count > 0 &&
- (last_event->type != KeyPress ||
- last_event->xkey.keycode != xevent->xkey.keycode)) {
+ ((last_event->type != KeyPress && last_event->type != xinput_types[XINPUT_TYPE_KEY_PRESS]) ||
+ !keycodes_equal (last_event, xevent))) {
+#ifdef DEBUG_GESTURES
+ g_message ("either last event not a keypress, or keycodes don't match. Resetting seq.");
+#endif
seq_count = 0;
}
@@ -648,15 +681,24 @@ gestures_filter (GdkXEvent *gdk_xevent,
* otherwise key gestures based on modifier keys such as
* Control_R won't work.
*/
- li = g_slist_find_custom (gesture_list, xevent, key_gesture_compare_func);
+ li = gesture_list_get_matches (gesture_list, xevent, key_gesture_compare_func);
if (li) {
curr_gesture = li->data;
+#ifdef DEBUG_GESTURES
+ g_message ("found a release match [%s]", curr_gesture->gesture_str);
+#endif
if ((curr_gesture->duration > 0) &&
- ((xevent->xkey.time - last_event->xkey.time) < curr_gesture->duration)) {
+ (elapsed_time (last_event, xevent) < curr_gesture->duration)) {
seq_count = 0;
curr_gesture = NULL;
+#ifdef DEBUG_GESTURES
+ g_message ("setting current gesture to NULL");
+#endif
} else {
seq_count++;
+#ifdef DEBUG_GESTURES
+ g_message ("incrementing seq_count");
+#endif
}
}
}
@@ -665,9 +707,13 @@ gestures_filter (GdkXEvent *gdk_xevent,
gint button = 0;
gint time = 0;
+
if (xevent->type == ButtonPress) {
button = xevent->xbutton.button;
time = xevent->xbutton.time;
+#ifdef DEBUG_GESTURES
+ g_message ("button press: %d", button);
+#endif
if (seq_count > 0 && (last_event->type != ButtonRelease))
seq_count = 0;
else if (seq_count > 0 && last_event->xbutton.button != button) {
@@ -678,6 +724,9 @@ gestures_filter (GdkXEvent *gdk_xevent,
else {
button = ((XDeviceButtonEvent *) xevent)->button;
time = ((XDeviceButtonEvent *) xevent)->time;
+#ifdef DEBUG_GESTURES
+ g_message ("xinput button press: %d", button);
+#endif
if (seq_count > 0 && last_event->type != xinput_types[XINPUT_TYPE_BUTTON_RELEASE]) {
seq_count = 0;
}
@@ -690,7 +739,7 @@ gestures_filter (GdkXEvent *gdk_xevent,
/*
* Find the associated gesture for this button.
*/
- li = g_slist_find_custom (gesture_list, xevent, key_gesture_compare_func);
+ li = gesture_list_get_matches (gesture_list, xevent, key_gesture_compare_func);
if (li) {
#ifdef DEBUG_GESTURES
g_message ("found match for press");
@@ -699,7 +748,7 @@ gestures_filter (GdkXEvent *gdk_xevent,
if (curr_gesture->timeout > 0 && seq_count > 0) {
/* xevent time values are in milliseconds. The config file spec is in ms */
if (curr_gesture->type ==
- (xevent->xbutton.time - last_event->xbutton.time) > curr_gesture->timeout) {
+ elapsed_time (last_event, xevent) > curr_gesture->timeout) {
seq_count = 0; /* Timeout has elapsed. Reset the sequence. */
curr_gesture = NULL;
#ifdef DEBUG_GESTURES
@@ -747,14 +796,14 @@ gestures_filter (GdkXEvent *gdk_xevent,
}
#endif
- li = g_slist_find_custom (gesture_list, xevent, key_gesture_compare_func);
+ li = gesture_list_get_matches (gesture_list, xevent, key_gesture_compare_func);
if (li) {
#ifdef DEBUG_GESTURES
g_message ("found match for release");
#endif
curr_gesture = li->data;
if ((curr_gesture->duration > 0) &&
- ((time - last_event->xbutton.time) < curr_gesture->duration)) {
+ (elapsed_time (last_event, xevent) < curr_gesture->duration)) {
seq_count = 0;
curr_gesture = NULL;
#ifdef DEBUG_GESTURES