[mousetweaks/at-spi2] Migrate to AT-SPI over DBus
- From: Gerd Kohlberger <gerdk src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [mousetweaks/at-spi2] Migrate to AT-SPI over DBus
- Date: Fri, 8 Jan 2010 18:16:03 +0000 (UTC)
commit d3533a3c0bbc4a392d0f902aae6e240c3dc4c7ce
Author: Gerd Kohlberger <gerdk src gnome org>
Date: Fri Jan 8 19:15:36 2010 +0100
Migrate to AT-SPI over DBus
src/mt-listener.c | 294 ++++++++++++++++++++++++++++++-----------------------
src/mt-listener.h | 19 ++--
src/mt-main.c | 257 +++++++++++++++++++++-------------------------
src/mt-main.h | 9 ++-
src/mt-service.c | 86 +++++++---------
src/mt-service.h | 12 +-
6 files changed, 343 insertions(+), 334 deletions(-)
---
diff --git a/src/mt-listener.c b/src/mt-listener.c
index 3d5d701..5284c36 100644
--- a/src/mt-listener.c
+++ b/src/mt-listener.c
@@ -17,52 +17,74 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
#include "mt-listener.h"
+#define SPI_EVENT_MOUSE_IFACE "org.freedesktop.atspi.Event.Mouse"
+#define SPI_SIGNAL_BUTTON "Button"
+#define SPI_SIGNAL_ABS "Abs"
+
+#define SPI_EVENT_FOCUS_IFACE "org.freedesktop.atspi.Event.Focus"
+#define SPI_SIGNAL_FOCUS "Focus"
+
+#define SPI_ACCESSIBLE_IFACE "org.freedesktop.atspi.Accessible"
+
struct _MtListenerPrivate {
- AccessibleEventListener *motion;
- AccessibleEventListener *button;
- AccessibleEventListener *focus;
- Accessible *current_focus;
+ DBusGConnection *connection;
+ DBusGProxy *focus;
+ guint track_focus : 1;
};
enum {
MOTION_EVENT,
BUTTON_EVENT,
- FOCUS_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
-static void mt_listener_dispose (GObject *object);
-static void mt_listener_motion_event (const AccessibleEvent *event,
- gpointer data);
-static void mt_listener_button_event (const AccessibleEvent *event,
- gpointer data);
-static void mt_listener_focus_event (const AccessibleEvent *event,
- gpointer data);
-
G_DEFINE_TYPE (MtListener, mt_listener, G_TYPE_OBJECT)
static void
+mt_listener_init (MtListener *listener)
+{
+ listener->priv = G_TYPE_INSTANCE_GET_PRIVATE (listener,
+ MT_TYPE_LISTENER,
+ MtListenerPrivate);
+}
+
+static void
+mt_listener_dispose (GObject *object)
+{
+ MtListenerPrivate *priv = MT_LISTENER (object)->priv;
+
+ if (priv->connection) {
+ dbus_g_connection_unref (priv->connection);
+ priv->connection = NULL;
+ }
+ if (priv->focus) {
+ g_object_unref (priv->focus);
+ priv->focus = NULL;
+ }
+ G_OBJECT_CLASS (mt_listener_parent_class)->dispose (object);
+}
+
+static void
mt_listener_class_init (MtListenerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = mt_listener_dispose;
- signals[MOTION_EVENT] =
+ signals[MOTION_EVENT] =
g_signal_new (g_intern_static_string ("motion_event"),
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE,
1, MT_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
-
- signals[BUTTON_EVENT] =
+ signals[BUTTON_EVENT] =
g_signal_new (g_intern_static_string ("button_event"),
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
@@ -70,152 +92,170 @@ mt_listener_class_init (MtListenerClass *klass)
g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE,
1, MT_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
- signals[FOCUS_CHANGED] =
- g_signal_new (g_intern_static_string ("focus_changed"),
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
g_type_class_add_private (klass, sizeof (MtListenerPrivate));
}
-static void
-mt_listener_init (MtListener *listener)
+static gboolean
+mt_listener_msg_to_event (MtListener *listener,
+ DBusMessage *msg,
+ MtEvent *event)
{
- MtListenerPrivate *priv;
-
- listener->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (listener,
- MT_TYPE_LISTENER,
- MtListenerPrivate);
-
- priv->motion = SPI_createAccessibleEventListener (mt_listener_motion_event,
- listener);
- SPI_registerGlobalEventListener (priv->motion, "mouse:abs");
-
- priv->button = SPI_createAccessibleEventListener (mt_listener_button_event,
- listener);
- SPI_registerGlobalEventListener (priv->button, "mouse:button:");
-
- priv->focus = SPI_createAccessibleEventListener (mt_listener_focus_event,
- listener);
- SPI_registerGlobalEventListener (priv->focus, "focus:");
+ DBusMessageIter iter;
+ dbus_uint32_t u;
+ char *s;
+ int type, arg = 1;
+
+ dbus_message_iter_init (msg, &iter);
+ while (dbus_message_iter_has_next (&iter))
+ {
+ type = dbus_message_iter_get_arg_type (&iter);
+ if (type == DBUS_TYPE_STRING) {
+ dbus_message_iter_get_basic (&iter, &s);
+ if (!s)
+ return FALSE;
+ if (*s == '\0') {
+ event->button = 0;
+ event->type = EV_MOTION;
+ }
+ else if (s[0] && s[1]) {
+ event->button = (guint) g_ascii_strtod (s, NULL);
+ event->type = s[1] == 'p' ? EV_BUTTON_PRESS : EV_BUTTON_RELEASE;
+ }
+ else
+ return FALSE;
+ }
+ else if (type == DBUS_TYPE_UINT32) {
+ dbus_message_iter_get_basic (&iter, &u);
+ if (arg++ == 1)
+ event->x = u;
+ else
+ event->y = u;
+ }
+ dbus_message_iter_next (&iter);
+ }
+ return TRUE;
}
-static void
-mt_listener_dispose (GObject *object)
+static DBusHandlerResult
+mt_listener_dispatch (DBusConnection *bus,
+ DBusMessage *msg,
+ gpointer data)
{
- MtListenerPrivate *priv = MT_LISTENER (object)->priv;
+ MtListener *listener = data;
+ MtEvent ev;
- if (priv->motion) {
- SPI_deregisterGlobalEventListenerAll (priv->motion);
- AccessibleEventListener_unref (priv->motion);
- priv->motion = NULL;
- }
- if (priv->button) {
- SPI_deregisterGlobalEventListenerAll (priv->button);
- AccessibleEventListener_unref (priv->button);
- priv->button = NULL;
+ if (dbus_message_has_sender (msg, DBUS_SERVICE_DBUS))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_has_member (msg, SPI_SIGNAL_ABS))
+ {
+ if (mt_listener_msg_to_event (listener, msg, &ev))
+ g_signal_emit (data, signals[MOTION_EVENT], 0, &ev);
}
- if (priv->focus) {
- SPI_deregisterGlobalEventListenerAll (priv->focus);
- AccessibleEventListener_unref (priv->focus);
- priv->focus = NULL;
+ else if (dbus_message_has_member (msg, SPI_SIGNAL_BUTTON))
+ {
+ if (mt_listener_msg_to_event (listener, msg, &ev))
+ g_signal_emit (data, signals[BUTTON_EVENT], 0, &ev);
}
- if (priv->current_focus) {
- Accessible_unref (priv->current_focus);
- priv->current_focus = NULL;
+ else if (listener->priv->track_focus &&
+ dbus_message_has_member (msg, SPI_SIGNAL_FOCUS))
+ {
+ if (listener->priv->focus)
+ g_object_unref (listener->priv->focus);
+
+ listener->priv->focus =
+ dbus_g_proxy_new_for_name (listener->priv->connection,
+ dbus_message_get_sender (msg),
+ dbus_message_get_path (msg),
+ SPI_ACCESSIBLE_IFACE);
}
-
- G_OBJECT_CLASS (mt_listener_parent_class)->dispose (object);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-GType
-mt_event_get_type (void)
-{
- static GType event = 0;
-
- if (G_UNLIKELY (event == 0))
- event = g_boxed_type_register_static (g_intern_static_string ("MtEvent"),
- (GBoxedCopyFunc) mt_event_copy,
- (GBoxedFreeFunc) mt_event_free);
- return event;
-}
-
-MtEvent *
-mt_event_copy (const MtEvent *event)
+static void
+mt_listener_setup_filter (MtListener *listener)
{
- return (MtEvent *) g_memdup (event, sizeof (MtEvent));
+ DBusConnection *bus;
+
+ bus = dbus_g_connection_get_connection (listener->priv->connection);
+ dbus_bus_add_match (bus,
+ "type='signal',"
+ "interface='" SPI_EVENT_MOUSE_IFACE "',"
+ "member='" SPI_SIGNAL_ABS "'",
+ NULL);
+ dbus_bus_add_match (bus,
+ "type='signal',"
+ "interface='" SPI_EVENT_MOUSE_IFACE "',"
+ "member='" SPI_SIGNAL_BUTTON "'",
+ NULL);
+ dbus_bus_add_match (bus,
+ "type='signal',"
+ "interface='" SPI_EVENT_FOCUS_IFACE "'",
+ NULL);
+ dbus_connection_add_filter (bus, mt_listener_dispatch, listener, NULL);
}
-void
-mt_event_free (MtEvent *event)
+MtListener *
+mt_listener_new (DBusGConnection *connection)
{
- g_free (event);
-}
+ MtListener *listener;
-static void
-mt_listener_motion_event (const AccessibleEvent *event, gpointer data)
-{
- MtEvent ev;
+ g_return_val_if_fail (connection != NULL, NULL);
- ev.type = EV_MOTION;
- ev.x = (gint) event->detail1;
- ev.y = (gint) event->detail2;
- ev.button = 0;
+ listener = g_object_new (MT_TYPE_LISTENER, NULL);
+ listener->priv->connection = dbus_g_connection_ref (connection);
+ mt_listener_setup_filter (listener);
- g_signal_emit (data, signals[MOTION_EVENT], 0, &ev);
+ return listener;
}
-static void
-mt_listener_button_event (const AccessibleEvent *event, gpointer data)
+DBusGProxy *
+mt_listener_current_focus (MtListener *listener)
{
- MtEvent ev;
+ g_return_val_if_fail (MT_IS_LISTENER (listener), NULL);
- /*
- * This is obviously dangerous, but it should be
- * guarantied that event-type strings will always
- * be in the form of "mouse:button:[1,2,3][p,r]"
- */
- ev.type = event->type[14] == 'p' ? EV_BUTTON_PRESS : EV_BUTTON_RELEASE;
- ev.x = (gint) event->detail1;
- ev.y = (gint) event->detail2;
- ev.button = event->type[13] == '1' ? 1 : (event->type[13] == '2' ? 2 : 3);
-
- g_signal_emit (data, signals[BUTTON_EVENT], 0, &ev);
+ if (listener->priv->track_focus && listener->priv->focus)
+ return g_object_ref (listener->priv->focus);
+ else
+ return NULL;
}
-static void
-mt_listener_focus_event (const AccessibleEvent *event, gpointer data)
+void
+mt_listener_track_focus (MtListener *listener,
+ gboolean track)
{
- MtListenerPrivate *priv = MT_LISTENER (data)->priv;
-
- if (event->source) {
- if (priv->current_focus)
- Accessible_unref (priv->current_focus);
+ MtListenerPrivate *priv;
- Accessible_ref (event->source);
- priv->current_focus = event->source;
+ g_return_if_fail (MT_IS_LISTENER (listener));
- g_signal_emit (data, signals[FOCUS_CHANGED], 0);
+ priv = listener->priv;
+ priv->track_focus = track;
+ if (!track && priv->focus) {
+ g_object_unref (priv->focus);
+ priv->focus = NULL;
}
}
-MtListener *
-mt_listener_get_default (void)
+GType
+mt_event_get_type (void)
{
- static MtListener *listener = NULL;
-
- if (!listener)
- listener = g_object_new (MT_TYPE_LISTENER, NULL);
+ static GType event = 0;
- return listener;
+ if (G_UNLIKELY (event == 0))
+ event = g_boxed_type_register_static (g_intern_static_string ("MtEvent"),
+ (GBoxedCopyFunc) mt_event_copy,
+ (GBoxedFreeFunc) mt_event_free);
+ return event;
}
-Accessible *
-mt_listener_current_focus (MtListener *listener)
+MtEvent *
+mt_event_copy (const MtEvent *event)
{
- g_return_val_if_fail (MT_IS_LISTENER (listener), NULL);
+ return g_memdup (event, sizeof (MtEvent));
+}
- return listener->priv->current_focus;
+void
+mt_event_free (MtEvent *event)
+{
+ g_free (event);
}
diff --git a/src/mt-listener.h b/src/mt-listener.h
index e000835..bacbbbd 100644
--- a/src/mt-listener.h
+++ b/src/mt-listener.h
@@ -20,10 +20,7 @@
#ifndef __MT_LISTENER_H__
#define __MT_LISTENER_H__
-#include <glib-object.h>
-#include <cspi/spi.h>
-
-G_BEGIN_DECLS
+#include <dbus/dbus-glib.h>
#define MT_TYPE_EVENT (mt_event_get_type ())
#define MT_TYPE_LISTENER (mt_listener_get_type ())
@@ -33,6 +30,8 @@ G_BEGIN_DECLS
#define MT_IS_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MT_TYPE_LISTENER))
#define MT_LISTENER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MT_TYPE_LISTENER, MtListenerClass))
+G_BEGIN_DECLS
+
typedef GObjectClass MtListenerClass;
typedef struct _MtListener MtListener;
typedef struct _MtListenerPrivate MtListenerPrivate;
@@ -43,8 +42,10 @@ struct _MtListener {
};
GType mt_listener_get_type (void) G_GNUC_CONST;
-MtListener * mt_listener_get_default (void);
-Accessible * mt_listener_current_focus (MtListener *listener);
+MtListener * mt_listener_new (DBusGConnection *connection);
+DBusGProxy * mt_listener_current_focus (MtListener *listener);
+void mt_listener_track_focus (MtListener *listener,
+ gboolean track);
typedef enum {
EV_MOTION = 0,
@@ -55,9 +56,9 @@ typedef enum {
typedef struct _MtEvent MtEvent;
struct _MtEvent {
MtEventType type;
- gint x;
- gint y;
- gint button;
+ guint x;
+ guint y;
+ guint button;
};
GType mt_event_get_type (void) G_GNUC_CONST;
diff --git a/src/mt-main.c b/src/mt-main.c
index f62fa60..662451e 100644
--- a/src/mt-main.c
+++ b/src/mt-main.c
@@ -22,26 +22,21 @@
#include <locale.h>
#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include <cspi/spi.h>
-#include <dbus/dbus-glib.h>
#include <X11/extensions/XTest.h>
+#include "mt-main.h"
#include "mt-common.h"
-#include "mt-service.h"
#include "mt-pidfile.h"
#include "mt-ctw.h"
-#include "mt-timer.h"
#include "mt-cursor-manager.h"
-#include "mt-cursor.h"
-#include "mt-main.h"
-#include "mt-listener.h"
-#include "mt-accessible.h"
#define GSM_DBUS_NAME "org.gnome.SessionManager"
#define GSM_DBUS_PATH "/org/gnome/SessionManager"
#define GSM_DBUS_INTERFACE "org.gnome.SessionManager"
+#define SPI_ACCESSIBLE_GET_ROLE "GetRole"
+#define ACCESSIBLE_ROLE_HYPERLINK 88
+
enum {
PRESS = 0,
RELEASE,
@@ -297,7 +292,7 @@ dwell_start_gesture (MtData *mt)
cursor = gdk_cursor_new (GDK_CROSS);
root = gdk_screen_get_root_window (mt_main_current_screen (mt));
gdk_pointer_grab (root, FALSE,
- GDK_POINTER_MOTION_MASK,
+ GDK_POINTER_MOTION_MASK,
NULL, cursor,
gtk_get_current_event_time ());
gdk_cursor_unref (cursor);
@@ -357,55 +352,25 @@ dwell_timer_finished (MtTimer *timer, gpointer data)
}
static gboolean
-eval_func (Accessible *a, gpointer data)
-{
- gchar *name;
- gboolean found = FALSE;
-
- name = Accessible_getName (a);
- if (name) {
- found = g_str_equal (name, "Window List");
- SPI_freeString (name);
- }
- return found;
-}
-
-static gboolean
-push_func (Accessible *a, gpointer data)
+hyperlink_is_focused (MtData *mt)
{
- MtData *mt = data;
- AccessibleRole role;
-
- role = Accessible_getRole (a);
- if (role != SPI_ROLE_PANEL && role != SPI_ROLE_EMBEDDED)
- return FALSE;
+ DBusGProxy *focus;
+ GError *error = NULL;
+ guint role = 0;
- if (!mt_accessible_is_visible (a))
+ focus = mt_listener_current_focus (mt->listener);
+ if (!focus)
return FALSE;
- if (Accessible_isComponent (a))
- return mt_accessible_in_extents (a, mt->pointer_x, mt->pointer_y);
-
- return TRUE;
-}
-
-static gboolean
-mt_main_use_move_release (MtData *mt)
-{
- Accessible *point, *search;
-
- point = mt_accessible_at_point (mt->pointer_x, mt->pointer_y);
- if (point) {
- search = mt_accessible_search (point,
- MT_SEARCH_TYPE_BREADTH,
- eval_func, push_func, mt);
- Accessible_unref (point);
- if (search) {
- Accessible_unref (search);
- return TRUE;
- }
+ dbus_g_proxy_call (focus, SPI_ACCESSIBLE_GET_ROLE, &error,
+ G_TYPE_INVALID, G_TYPE_UINT, &role, G_TYPE_INVALID);
+ if (error) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
}
- return FALSE;
+ g_object_unref (focus);
+
+ return role == ACCESSIBLE_ROLE_HYPERLINK;
}
static gboolean
@@ -426,7 +391,7 @@ delay_timer_finished (MtTimer *timer, gpointer data)
mt_cursor_manager_restore_all (mt_cursor_manager_get_default ());
- if (mt->move_release || mt_main_use_move_release (mt)) {
+ if (hyperlink_is_focused (mt)) {
/* release the click outside of the focused object to
* abort any action started by button-press.
*/
@@ -492,7 +457,7 @@ global_motion_event (MtListener *listener,
mt->pointer_x, mt->pointer_y,
mt->x_old, mt->y_old);
}
- mt_main_draw_line (mt,
+ mt_main_draw_line (mt,
mt->pointer_x, mt->pointer_y,
event->x, event->y);
mt->x_old = event->x;
@@ -519,32 +484,13 @@ global_button_event (MtListener *listener,
mt_cursor_manager_restore_all (mt_cursor_manager_get_default ());
}
}
- /*
- * cancel a dwell-click in progress if a physical button
- * is pressed - useful for mixed use-cases and testing
- */
+ /* cancel a dwell-click in progress if a physical button is pressed */
if ((event->type == EV_BUTTON_PRESS && mt_timer_is_running (mt->dwell_timer)) ||
(event->type == EV_BUTTON_RELEASE && mt->dwell_drag_started)) {
mt_dwell_click_cancel (mt);
}
}
-static void
-global_focus_event (MtListener *listener,
- gpointer data)
-{
- MtData *mt = data;
- Accessible *accessible;
-
- if (mt->delay_enabled) {
- accessible = mt_listener_current_focus (listener);
- /* TODO: check for more objects and conditions.
- * Some links don't have jump actions, eg: text-mails in thunderbird.
- */
- mt->move_release = mt_accessible_supports_action (accessible, "jump");
- }
-}
-
static gboolean
cursor_overlay_time (MtData *mt,
guchar *image,
@@ -669,8 +615,10 @@ gconf_value_changed (GConfClient *client,
if (g_str_equal (key, OPT_THRESHOLD) && value->type == GCONF_VALUE_INT)
mt->threshold = gconf_value_get_int (value);
- else if (g_str_equal (key, OPT_DELAY) && value->type == GCONF_VALUE_BOOL)
+ else if (g_str_equal (key, OPT_DELAY) && value->type == GCONF_VALUE_BOOL) {
mt->delay_enabled = gconf_value_get_bool (value);
+ mt_listener_track_focus (mt->listener, mt->delay_enabled);
+ }
else if (g_str_equal (key, OPT_DELAY_T) && value->type == GCONF_VALUE_FLOAT)
mt_timer_set_target (mt->delay_timer, gconf_value_get_float (value));
else if (g_str_equal (key, OPT_DWELL) && value->type == GCONF_VALUE_BOOL) {
@@ -751,33 +699,35 @@ get_gconf_options (MtData *mt)
static void
mt_main_request_logout (MtData *mt)
{
- DBusGConnection *bus;
DBusGProxy *proxy;
+ GError *error = NULL;
- bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
- if (bus) {
- proxy = dbus_g_proxy_new_for_name (bus,
- GSM_DBUS_NAME,
- GSM_DBUS_PATH,
- GSM_DBUS_INTERFACE);
- /*
- * Call logout method of session manager:
- * mode: 0 = normal, 1 = no confirmation, 2 = force
- */
- dbus_g_proxy_call (proxy, "Logout", NULL,
- G_TYPE_UINT, 1, G_TYPE_INVALID,
- G_TYPE_INVALID);
- g_object_unref (proxy);
+ proxy = dbus_g_proxy_new_for_name (mt->session_bus,
+ GSM_DBUS_NAME,
+ GSM_DBUS_PATH,
+ GSM_DBUS_INTERFACE);
+ /*
+ * Call the Logout method of the session manager:
+ * mode: 0 = normal, 1 = no confirmation, 2 = force
+ */
+ dbus_g_proxy_call (proxy, "Logout", NULL,
+ G_TYPE_UINT, 1, G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ g_object_unref (proxy);
+ if (error) {
+ g_warning ("Logout: %s", error->message);
+ g_error_free (error);
}
}
static gboolean
-accessibility_enabled (MtData *mt,
- gint spi_status)
+accessibility_enabled (MtData *mt)
{
+ gboolean a11y;
gint ret;
- if (spi_status != 0) {
+ a11y = gconf_client_get_bool (mt->client, GNOME_A11Y_KEY, NULL);
+ if (!a11y) {
ret = mt_common_show_dialog
(_("Assistive Technology Support is not Enabled"),
_("Mousetweaks requires assistive technologies to be enabled "
@@ -792,7 +742,7 @@ accessibility_enabled (MtData *mt,
mt_main_request_logout (mt);
}
else {
- /* reset the selected option again */
+ /* reset the selected option */
if (gconf_client_get_bool (mt->client, OPT_DELAY, NULL))
gconf_client_set_bool (mt->client, OPT_DELAY, FALSE, NULL);
if (gconf_client_get_bool (mt->client, OPT_DWELL, NULL))
@@ -803,6 +753,30 @@ accessibility_enabled (MtData *mt,
return TRUE;
}
+static DBusGConnection *
+mt_main_get_accessibility_bus (void)
+{
+ DBusGConnection *bus = NULL;
+ Display *dpy = GDK_DISPLAY ();
+ Atom at;
+ gint af;
+ gulong nitems, bytes;
+ guchar *bus_addr;
+
+ gdk_error_trap_push ();
+ if (XGetWindowProperty (dpy, XDefaultRootWindow (dpy),
+ XInternAtom (dpy, "AT_SPI_BUS", FALSE),
+ 0L, 32L, False, AnyPropertyType,
+ &at, &af, &nitems, &bytes, &bus_addr) == Success) {
+ if (at != None && af == 8)
+ bus = dbus_g_connection_open ((gchar *) bus_addr, NULL);
+
+ XFree (bus_addr);
+ }
+ gdk_error_trap_pop ();
+ return bus;
+}
+
static MtData *
mt_data_init (void)
{
@@ -816,10 +790,23 @@ mt_data_init (void)
&ev_base, &err_base, &maj, &min)) {
XCloseDisplay (mt->xtst_display);
g_slice_free (MtData, mt);
- g_critical ("No XTest extension found. Aborting..");
+ g_print ("No XTest extension found. Aborting.");
+ return NULL;
+ }
+
+ mt->session_bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+ if (!mt->session_bus) {
+ g_print ("No connection to DBus session bus. Aborting.");
+ XCloseDisplay (mt->xtst_display);
+ g_slice_free (MtData, mt);
return NULL;
}
+ /* connect to a11y bus, if it is not available reuse the session bus */
+ mt->a11y_bus = mt_main_get_accessibility_bus ();
+ if (!mt->a11y_bus)
+ mt->a11y_bus = dbus_g_connection_ref (mt->session_bus);
+
mt->client = gconf_client_get_default ();
gconf_client_add_dir (mt->client, GNOME_MOUSE_DIR,
GCONF_CLIENT_PRELOAD_NONE, NULL);
@@ -840,7 +827,7 @@ mt_data_init (void)
g_signal_connect (mt->dwell_timer, "tick",
G_CALLBACK (mt_main_timer_tick), mt);
- mt->service = mt_service_get_default ();
+ mt->service = mt_service_new (mt->session_bus);
mt_service_set_clicktype (mt->service, DWELL_CLICK_TYPE_SINGLE, NULL);
mt->n_screens = gdk_display_get_n_screens (gdk_display_get_default ());
@@ -854,17 +841,22 @@ mt_data_init (void)
static void
mt_data_free (MtData *mt)
{
- g_object_unref (mt->delay_timer);
- g_object_unref (mt->dwell_timer);
- g_object_unref (mt->service);
- g_object_unref (mt->client);
-
- if (mt->ui) {
- gtk_widget_destroy (mt_ctw_get_window (mt));
- g_object_unref (mt->ui);
- }
+ if (mt) {
+ g_object_unref (mt->delay_timer);
+ g_object_unref (mt->dwell_timer);
+ g_object_unref (mt->service);
+ g_object_unref (mt->client);
+ dbus_g_connection_unref (mt->session_bus);
+ dbus_g_connection_unref (mt->a11y_bus);
+ XCloseDisplay (mt->xtst_display);
+
+ if (mt->ui) {
+ gtk_widget_destroy (mt_ctw_get_window (mt));
+ g_object_unref (mt->ui);
+ }
- g_slice_free (MtData, mt);
+ g_slice_free (MtData, mt);
+ }
}
static MtCliArgs
@@ -929,12 +921,11 @@ mt_main (int argc, char **argv, MtCliArgs cli_args)
{
MtData *mt;
MtCursorManager *manager;
- MtListener *listener;
- gint spi_status;
- gint spi_leaks = 0;
+
+ gtk_init (&argc, &argv);
if (mt_pidfile_create () < 0) {
- g_warning ("Couldn't create PID file.");
+ g_print ("Could not create PID file. Aborting.");
return;
}
@@ -943,20 +934,12 @@ mt_main (int argc, char **argv, MtCliArgs cli_args)
signal (SIGQUIT, signal_handler);
signal (SIGHUP, signal_handler);
- gtk_init (&argc, &argv);
+ if (!(mt = mt_data_init ()))
+ goto out;
- mt = mt_data_init ();
- if (!mt)
- goto FINISH;
-
- spi_status = SPI_init ();
- /* don't check a11y key in login mode */
- if (!cli_args.login) {
- if (!accessibility_enabled (mt, spi_status)) {
- mt_data_free (mt);
- goto FINISH;
- }
- }
+ if (!cli_args.login)
+ if (!accessibility_enabled (mt))
+ goto out;
/* load gconf settings */
get_gconf_options (mt);
@@ -985,9 +968,9 @@ mt_main (int argc, char **argv, MtCliArgs cli_args)
g_free (cli_args.mode);
}
- /* init click-type windoe */
+ /* init click-type window */
if (!mt_ctw_init (mt, cli_args.pos_x, cli_args.pos_y))
- goto CLEANUP;
+ goto out;
/* init cursor animation */
manager = mt_cursor_manager_get_default ();
@@ -998,29 +981,21 @@ mt_main (int argc, char **argv, MtCliArgs cli_args)
G_CALLBACK (cursor_cache_cleared), mt);
/* init at-spi signals */
- listener = mt_listener_get_default ();
- g_signal_connect (listener, "motion_event",
+ mt->listener = mt_listener_new (mt->a11y_bus);
+ mt_listener_track_focus (mt->listener, mt->delay_enabled);
+ g_signal_connect (mt->listener, "motion_event",
G_CALLBACK (global_motion_event), mt);
- g_signal_connect (listener, "button_event",
+ g_signal_connect (mt->listener, "button_event",
G_CALLBACK (global_button_event), mt);
- g_signal_connect (listener, "focus_changed",
- G_CALLBACK (global_focus_event), mt);
gtk_main ();
mt_cursor_manager_restore_all (manager);
g_object_unref (manager);
- g_object_unref (listener);
-
-CLEANUP:
- spi_leaks = SPI_exit ();
+ g_object_unref (mt->listener);
+out:
mt_data_free (mt);
-FINISH:
mt_pidfile_remove ();
-
- if (spi_leaks)
- g_warning ("AT-SPI reported %i leak%s.",
- spi_leaks, spi_leaks != 1 ? "s" : "");
}
int
diff --git a/src/mt-main.h b/src/mt-main.h
index beedd94..d4ff5bb 100644
--- a/src/mt-main.h
+++ b/src/mt-main.h
@@ -22,21 +22,27 @@
#include <gdk/gdkx.h>
#include <gconf/gconf-client.h>
+#include <dbus/dbus-glib.h>
#include "mt-timer.h"
#include "mt-service.h"
#include "mt-cursor.h"
+#include "mt-listener.h"
G_BEGIN_DECLS
typedef struct _MtData MtData;
struct _MtData {
+ DBusGConnection *session_bus;
+ DBusGConnection *a11y_bus;
+
GConfClient *client;
GtkBuilder *ui;
MtService *service;
MtTimer *delay_timer;
MtTimer *dwell_timer;
MtCursor *cursor;
+ MtListener *listener;
Display *xtst_display;
gint n_screens;
gint direction;
@@ -54,13 +60,12 @@ struct _MtData {
guint dwell_enabled : 1;
guint dwell_show_ctw : 1;
guint animate_cursor : 1;
+ guint left_handed : 1;
/* state flags */
- guint left_handed : 1;
guint dwell_drag_started : 1;
guint dwell_gesture_started : 1;
guint override_cursor : 1;
- guint move_release : 1;
};
G_END_DECLS
diff --git a/src/mt-service.c b/src/mt-service.c
index e664cc8..aec13f7 100644
--- a/src/mt-service.c
+++ b/src/mt-service.c
@@ -17,7 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-bindings.h>
#include "mt-service.h"
@@ -27,7 +26,8 @@
#define MOUSETWEAKS_DBUS_PATH "/org/gnome/Mousetweaks"
struct _MtServicePrivate {
- guint clicktype;
+ DBusGConnection *connection;
+ guint clicktype;
};
enum {
@@ -40,8 +40,26 @@ static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (MtService, mt_service, G_TYPE_OBJECT)
-static void mt_service_dispose (GObject *object);
-static void mt_service_register (MtService *service);
+static void
+mt_service_init (MtService *service)
+{
+ service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service,
+ MT_TYPE_SERVICE,
+ MtServicePrivate);
+}
+
+static void
+mt_service_dispose (GObject *object)
+{
+ MtServicePrivate *priv = MT_SERVICE (object)->priv;
+
+ if (priv->connection) {
+ g_signal_emit (object, signals[STATUS_CHANGED], 0, FALSE);
+ dbus_g_connection_unref (priv->connection);
+ priv->connection = NULL;
+ }
+ G_OBJECT_CLASS (mt_service_parent_class)->dispose (object);
+}
static void
mt_service_class_init (MtServiceClass *klass)
@@ -71,43 +89,17 @@ mt_service_class_init (MtServiceClass *klass)
&dbus_glib_mt_service_object_info);
}
-static void
-mt_service_init (MtService *service)
-{
- service->priv = G_TYPE_INSTANCE_GET_PRIVATE (service,
- MT_TYPE_SERVICE,
- MtServicePrivate);
- mt_service_register (service);
-}
-
-static void
-mt_service_dispose (GObject *object)
-{
- g_signal_emit (object, signals[STATUS_CHANGED], 0, FALSE);
-
- G_OBJECT_CLASS (mt_service_parent_class)->dispose (object);
-}
-
-static void
+static gboolean
mt_service_register (MtService *service)
{
- DBusGConnection *bus;
DBusGProxy *proxy;
GError *error = NULL;
guint result;
- bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
- if (bus == NULL) {
- g_warning ("Unable to connect to session bus: %s", error->message);
- g_error_free (error);
- return;
- }
-
- proxy = dbus_g_proxy_new_for_name (bus,
+ proxy = dbus_g_proxy_new_for_name (service->priv->connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
-
if (!dbus_g_proxy_call (proxy, "RequestName", &error,
G_TYPE_STRING, MOUSETWEAKS_DBUS_SERVICE,
G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
@@ -117,34 +109,32 @@ mt_service_register (MtService *service)
g_warning ("Unable to acquire name: %s", error->message);
g_error_free (error);
g_object_unref (proxy);
- return;
+ return FALSE;
}
-
g_object_unref (proxy);
if (result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
- dbus_g_connection_register_g_object (bus,
+ dbus_g_connection_register_g_object (service->priv->connection,
MOUSETWEAKS_DBUS_PATH,
G_OBJECT (service));
else
g_warning ("DBus: Not primary name owner.");
-}
-static MtService *
-mt_service_new (void)
-{
- return g_object_new (MT_TYPE_SERVICE, NULL);
+ return TRUE;
}
MtService *
-mt_service_get_default (void)
+mt_service_new (DBusGConnection *connection)
{
- static MtService *service = NULL;
+ MtService *service;
- if (!service) {
- service = mt_service_new ();
- g_signal_emit (service, signals[STATUS_CHANGED], 0, TRUE);
- }
+ g_return_val_if_fail (connection != NULL, NULL);
+
+ service = g_object_new (MT_TYPE_SERVICE, NULL);
+ service->priv->connection = dbus_g_connection_ref (connection);
+
+ mt_service_register (service);
+ g_signal_emit (service, signals[STATUS_CHANGED], 0, TRUE);
return service;
}
@@ -157,10 +147,8 @@ mt_service_set_clicktype (MtService *service,
g_return_val_if_fail (MT_IS_SERVICE (service), FALSE);
service->priv->clicktype = clicktype;
+ g_signal_emit (service, signals[CLICKTYPE_CHANGED], 0, clicktype);
- g_signal_emit (service,
- signals[CLICKTYPE_CHANGED],
- 0, service->priv->clicktype);
return TRUE;
}
diff --git a/src/mt-service.h b/src/mt-service.h
index 602824f..3992a9b 100644
--- a/src/mt-service.h
+++ b/src/mt-service.h
@@ -20,7 +20,7 @@
#ifndef __MT_SERVICE_H__
#define __MT_SERVICE_H__
-#include <glib-object.h>
+#include <dbus/dbus-glib.h>
G_BEGIN_DECLS
@@ -41,11 +41,11 @@ struct _MtService {
};
GType mt_service_get_type (void) G_GNUC_CONST;
-MtService * mt_service_get_default (void);
-gboolean mt_service_set_clicktype (MtService *service,
- guint clicktype,
- GError **error);
-guint mt_service_get_clicktype (MtService *service);
+MtService * mt_service_new (DBusGConnection *connection);
+gboolean mt_service_set_clicktype (MtService *service,
+ guint clicktype,
+ GError **error);
+guint mt_service_get_clicktype (MtService *service);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]