Eitan Isaacson has proposed merging lp:~eeejay/notify-osd/text_iface into 
lp:notify-osd.

Requested reviews:
    Notify OSD Developers (notify-osd-developers)

This branch adds a text interface and relevant AT-SPI events for dynamic bubble 
messages and titles.
-- 
https://code.launchpad.net/~eeejay/notify-osd/text_iface/+merge/5919
Your team Notify OSD Developers is subscribed to branch lp:notify-osd.
=== modified file 'src/bubble-window-accessible.c'
--- src/bubble-window-accessible.c	2009-02-27 20:00:53 +0000
+++ src/bubble-window-accessible.c	2009-04-27 08:45:53 +0000
@@ -37,6 +37,7 @@
 static void        bubble_window_real_initialize            (AtkObject*                   obj,
                                                              gpointer                     data);
 static void        atk_value_interface_init                 (AtkValueIface*               iface);
+static void        atk_text_interface_init                  (AtkTextIface*                iface);
 static void        bubble_window_get_current_value          (AtkValue*                    obj,
                                                              GValue*                      value);
 static void        bubble_window_get_maximum_value          (AtkValue*                    obj,
@@ -46,6 +47,19 @@
 static void        bubble_value_changed_event               (Bubble*                      bubble,
                                                              gint                         value,
                                                              AtkObject                   *obj);
+static void        bubble_message_body_deleted_event        (Bubble*                      bubble,
+                                                             const gchar*                 text,
+                                                             AtkObject*                   obj);
+static void        bubble_message_body_inserted_event       (Bubble*                      bubble,
+                                                             const gchar*                 text,
+                                                             AtkObject*                   obj);
+
+static gchar*      bubble_window_get_text                   (AtkText                     *obj,
+															 gint                         start_offset,
+															 gint                         end_offset);
+static gint        bubble_window_get_character_count        (AtkText                     *obj);
+static gunichar    bubble_window_get_character_at_offset    (AtkText                     *obj,
+                                                             gint                         offset);
 
 static void* bubble_window_accessible_parent_class;
 
@@ -76,6 +90,13 @@
             (GInterfaceFinalizeFunc) NULL,
             NULL
         };
+
+        const GInterfaceInfo atk_text_info = 
+        {
+            (GInterfaceInitFunc) atk_text_interface_init,
+            (GInterfaceFinalizeFunc) NULL,
+            NULL
+        };
         
         /*
          * Figure out the size of the class and instance
@@ -100,6 +121,8 @@
                                        "BubbleWindowAccessible", &tinfo, 0);
 
         g_type_add_interface_static (type, ATK_TYPE_VALUE, &atk_value_info);
+
+        g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info);
     }
     
     return type;
@@ -116,6 +139,17 @@
 }
 
 static void
+atk_text_interface_init (AtkTextIface* iface)
+{
+    g_return_if_fail (iface != NULL);
+
+	iface->get_text = bubble_window_get_text;
+	iface->get_character_count = bubble_window_get_character_count;
+    iface->get_character_at_offset = bubble_window_get_character_at_offset;
+
+}
+
+static void
 bubble_window_accessible_init (BubbleWindowAccessible *object)
 {
 	/* TODO: Add initialization code here */
@@ -160,6 +194,16 @@
                       G_CALLBACK (bubble_value_changed_event),
                       obj);
 
+    g_signal_connect (bubble,
+                      "message-body-deleted",
+                      G_CALLBACK (bubble_message_body_deleted_event),
+                      obj);
+
+    g_signal_connect (bubble,
+                      "message-body-inserted",
+                      G_CALLBACK (bubble_message_body_inserted_event),
+                      obj);
+
 }
 
 AtkObject*
@@ -286,3 +330,108 @@
 {
     g_object_notify (G_OBJECT (obj), "accessible-value");
 }
+
+static void
+bubble_message_body_deleted_event (Bubble*      bubble,
+                                   const gchar* text,
+                                   AtkObject*   obj)
+{
+    /* Not getting very fancy here, delete is always complete */
+    g_signal_emit_by_name (
+        obj, "text_changed::delete", 0, g_utf8_strlen (text, -1));    
+}
+
+static void
+bubble_message_body_inserted_event (Bubble*      bubble,
+                                  const gchar* text,
+                                  AtkObject*   obj)
+{
+    const gchar* message_body;
+
+    message_body = bubble_get_message_body (bubble);
+
+    g_signal_emit_by_name (
+        obj, "text_changed::insert",
+        g_utf8_strlen (message_body, -1) - g_utf8_strlen (text, -1),
+        g_utf8_strlen (message_body, -1));    
+}
+
+static gchar*
+bubble_window_get_text (AtkText *obj,
+						gint    start_offset,
+						gint    end_offset)
+{
+    GtkAccessible* accessible;
+ 	Bubble*        bubble;
+	const gchar*   body_text;
+    gsize          char_length;
+	glong          body_strlen;
+
+	g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), g_strdup(""));
+
+ 	accessible = GTK_ACCESSIBLE (obj);
+
+	g_return_val_if_fail (accessible->widget == NULL, g_strdup(""));
+ 	
+ 	bubble = g_object_get_data (G_OBJECT(accessible->widget), "bubble");
+
+	if (end_offset <= start_offset)
+		return g_strdup("");
+
+	body_text = bubble_get_message_body (bubble);
+
+	body_strlen = g_utf8_strlen(body_text, -1);
+
+	if (start_offset > body_strlen)
+		start_offset = body_strlen;
+
+	if (end_offset > body_strlen || end_offset == -1)
+		end_offset = body_strlen;
+
+
+    char_length = g_utf8_offset_to_pointer (body_text, end_offset) - 
+        g_utf8_offset_to_pointer (body_text, start_offset);
+    
+	return g_strndup (g_utf8_offset_to_pointer(body_text, start_offset), 
+					  char_length);
+}
+
+static gint
+bubble_window_get_character_count (AtkText *obj)
+{
+	GtkAccessible* accessible;
+ 	Bubble*        bubble;
+
+ 	g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), 0);
+ 	
+ 	accessible = GTK_ACCESSIBLE (obj);
+    
+    if (accessible->widget == NULL)
+        return 0;
+ 	
+ 	bubble = g_object_get_data (G_OBJECT(accessible->widget), "bubble");
+
+	return g_utf8_strlen(bubble_get_message_body (bubble), -1);
+}
+
+static gunichar
+bubble_window_get_character_at_offset (AtkText *obj,
+                                       gint    offset)
+{
+	GtkAccessible* accessible;
+ 	Bubble*        bubble;
+    const gchar*   body_text;
+
+ 	g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), 0);
+ 	
+ 	accessible = GTK_ACCESSIBLE (obj);
+    
+    if (accessible->widget == NULL)
+        return 0;
+ 	
+ 	bubble = g_object_get_data (G_OBJECT(accessible->widget), "bubble");
+
+	body_text = bubble_get_message_body (bubble);
+
+    return g_utf8_get_char (g_utf8_offset_to_pointer (body_text, offset));
+}

=== modified file 'src/bubble.c'
--- src/bubble.c	2009-04-16 14:13:47 +0000
+++ src/bubble.c	2009-04-27 08:54:00 +0000
@@ -94,6 +94,8 @@
 {
 	TIMED_OUT,
 	VALUE_CHANGED,
+	MESSAGE_BODY_DELETED,
+	MESSAGE_BODY_INSERTED,
 	LAST_SIGNAL
 };
 
@@ -1903,6 +1905,30 @@
 		G_TYPE_NONE,
 		1,
         G_TYPE_INT);
+
+    g_bubble_signals[MESSAGE_BODY_DELETED] = g_signal_new (
+		"message-body-deleted",
+		G_OBJECT_CLASS_TYPE (gobject_class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (BubbleClass, message_body_deleted),
+		NULL,
+		NULL,
+		g_cclosure_marshal_VOID__STRING,
+		G_TYPE_NONE,
+		1,
+        G_TYPE_STRING);
+
+    g_bubble_signals[MESSAGE_BODY_INSERTED] = g_signal_new (
+		"message-body-inserted",
+		G_OBJECT_CLASS_TYPE (gobject_class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (BubbleClass, message_body_inserted),
+		NULL,
+		NULL,
+		g_cclosure_marshal_VOID__STRING,
+		G_TYPE_NONE,
+		1,
+        G_TYPE_STRING);
 }
 
 /*-- public API --------------------------------------------------------------*/
@@ -2066,6 +2092,10 @@
 		g_string_free (priv->title, TRUE);
 
 	priv->title = g_string_new (title);
+
+	g_object_notify (
+		G_OBJECT (gtk_widget_get_accessible (GET_PRIVATE(self)->widget)), 
+		"accessible-name");
 }
 
 const gchar*
@@ -2089,13 +2119,20 @@
 
 	priv = GET_PRIVATE (self);
 
-	if (priv->message_body->len != 0)
+	if (priv->message_body->len != 0) {
+		g_signal_emit (self, g_bubble_signals[MESSAGE_BODY_DELETED], 
+					   0, priv->message_body->str);
 		g_string_free (priv->message_body, TRUE);
-
+    }
 	/* filter out any HTML/markup if possible */
 	text = filter_text (body);
 
 	priv->message_body = g_string_new (text);
+
+	g_signal_emit (self, g_bubble_signals[MESSAGE_BODY_INSERTED], 0, text);
+	g_object_notify (G_OBJECT (gtk_widget_get_accessible (priv->widget)), 
+					 "accessible-description");
+
 	g_free (text);
 }
 
@@ -3387,6 +3424,12 @@
 	/* append text to current message-body */
 	g_string_append (GET_PRIVATE (self)->message_body, text);
 
+	g_signal_emit (self, g_bubble_signals[MESSAGE_BODY_INSERTED], 0, text);
+
+	g_object_notify (
+		G_OBJECT (gtk_widget_get_accessible (GET_PRIVATE(self)->widget)), 
+		"accessible-description");
+
 	g_free ((gpointer) text);
 }
 

=== modified file 'src/bubble.h'
--- src/bubble.h	2009-04-09 10:44:07 +0000
+++ src/bubble.h	2009-04-23 15:22:58 +0000
@@ -76,6 +76,8 @@
 	/*< signals >*/
 	void (*timed_out) (Bubble* bubble);
 	void (*value_changed) (Bubble* bubble);
+	void (*message_body_deleted) (Bubble* bubble);
+	void (*message_body_inserted) (Bubble* bubble);
 };
 
 GType bubble_get_type (void);

_______________________________________________
Mailing list: https://launchpad.net/~dx-team
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~dx-team
More help   : https://help.launchpad.net/ListHelp

Reply via email to