[caribou] Extended with ATK



commit 968bf82e18a9f01e59a0808d837f90663c989219
Author: Eitan Isaacson <eitan monotonous org>
Date:   Mon Jun 6 13:20:45 2011 -0700

    Extended with ATK
    
    To support location hints for web widgets in Epiphany and Firefox.

 im/gtk2/Makefile.am            |    5 ++-
 im/gtk2/vapi-fixes.vapi        |    1 +
 im/gtk3/Makefile.am            |    5 ++-
 im/gtk3/caribou-imcontext.vala |  100 +++++++++++++++++++++++++++++++++++----
 im/gtk3/vapi-fixes.vapi        |   10 ++++
 5 files changed, 108 insertions(+), 13 deletions(-)
---
diff --git a/im/gtk2/Makefile.am b/im/gtk2/Makefile.am
index fe164fd..6c8dea4 100644
--- a/im/gtk2/Makefile.am
+++ b/im/gtk2/Makefile.am
@@ -8,6 +8,8 @@ im_caribou_la_SOURCES = \
 
 im_caribou_la_VALAFLAGS = \
 	-h caribou-imcontext.h \
+    --vapidir=. \
+	--pkg vapi-fixes \
 	--pkg gtk+-2.0 \
 	-D GTK2 \
 	$(VALAGLAFS)
@@ -27,4 +29,5 @@ im_caribou_la_LDFLAGS = \
         $(NULL)
 
 EXTRA_DIST = \
-        $(NULL)
+	vapi-fixes.vapi \
+	$(NULL)
diff --git a/im/gtk2/vapi-fixes.vapi b/im/gtk2/vapi-fixes.vapi
new file mode 120000
index 0000000..cb1b309
--- /dev/null
+++ b/im/gtk2/vapi-fixes.vapi
@@ -0,0 +1 @@
+../gtk3/vapi-fixes.vapi
\ No newline at end of file
diff --git a/im/gtk3/Makefile.am b/im/gtk3/Makefile.am
index 9cd956c..4863c55 100644
--- a/im/gtk3/Makefile.am
+++ b/im/gtk3/Makefile.am
@@ -8,6 +8,8 @@ im_caribou_la_SOURCES = \
 
 im_caribou_la_VALAFLAGS = \
 	-h caribou-imcontext.h \
+    --vapidir=. \
+	--pkg vapi-fixes \
 	--pkg gtk+-3.0 \
 	$(VALAGLAFS)
 
@@ -26,4 +28,5 @@ im_caribou_la_LDFLAGS = \
         $(NULL)
 
 EXTRA_DIST = \
-        $(NULL)
+	vapi-fixes.vapi \
+	$(NULL)
diff --git a/im/gtk3/caribou-imcontext.vala b/im/gtk3/caribou-imcontext.vala
index a8d5033..ac3e43c 100644
--- a/im/gtk3/caribou-imcontext.vala
+++ b/im/gtk3/caribou-imcontext.vala
@@ -1,8 +1,10 @@
 namespace Caribou {
     [DBus(name = "org.gnome.Caribou.Keyboard")]
     interface Keyboard : Object {
-        public abstract void set_cursor_location (int x, int y, int w, int h) throws IOError;
-        public abstract void set_entry_location (int x, int y, int w, int h) throws IOError;
+        public abstract void set_cursor_location (int x, int y, int w, int h)
+            throws IOError;
+        public abstract void set_entry_location (int x, int y, int w, int h)
+            throws IOError;
         public abstract void show () throws IOError;
         public abstract void hide () throws IOError;
     }
@@ -14,24 +16,99 @@ namespace Caribou {
         public IMContext () {
         }
 
-        public override void focus_in () {
-            int x, y, w, h;
+        private void get_origin_geometry (Gdk.Window window,
+                                          out int x, out int y,
+                                          out int w, out int h) {
             window.get_origin (out x, out y);
 #if GTK2
             window.get_geometry (null, null, out w, out h, null);
 #else
             window.get_geometry (null, null, out w, out h);
 #endif
-            stdout.printf ("focus_in %d %d\n", x, y);
-            try {
-                keyboard.show ();
-                keyboard.set_entry_location (x, y, w, h);
-            } catch (IOError e) {
-                stderr.printf ("%s\n", e.message);
+        }
+
+        private Atk.Object? find_focused_accessible (Atk.Object acc) {          
+            Atk.StateSet state = acc.ref_state_set ();
+
+            bool match = (state.contains_state (Atk.StateType.EDITABLE) &&
+                          state.contains_state (Atk.StateType.FOCUSED) &&
+                          acc.get_n_accessible_children () == 0);
+
+            if (match)
+                return acc;
+
+            for (int i=0;i<acc.get_n_accessible_children ();i++) {
+                 Atk.Object child = acc.ref_accessible_child (i);
+                 Atk.Object focused_child = find_focused_accessible (child);
+                 if (focused_child != null)
+                     return focused_child;
+            }
+
+            return null;
+        }
+
+        private bool get_acc_geometry (Atk.Object acc,
+                                       out int x, out int y, out int w, out int h) {
+            Atk.Object child = find_focused_accessible (acc);
+
+            if (child == null)
+                return false;
+
+            if (!(child is Atk.Component)) {
+                stderr.printf ("Accessible is not a component\n");
+                return false;
             }
+
+            Atk.component_get_extents ((Atk.Component) child,
+                                       out x, out y, out w, out h,
+                                       Atk.CoordType.SCREEN);
+            return true;
         }
 
+        private Gtk.Widget get_window_widget () {
+            void *p = null;
+            window.get_user_data (&p);
+            return p as Gtk.Widget;
+        }
+
+        public override void focus_in () {
+            GLib.Timeout.add (100, () => {
+                    int x=0, y=0, w=0, h=0;
+                    Gtk.Widget widget = get_window_widget ();
+
+                    if (widget is Gtk.Editable) {
+                        /* Well behaved app */
+                        stdout.printf ("Well behaved app!\n");
+                        get_origin_geometry (window, out x, out y, out w, out h);
+                    } else { 
+                        Atk.Object acc = widget.get_accessible ();
+                        if (acc.get_role () == Atk.Role.REDUNDANT_OBJECT) {
+                            /* It is probably Gecko */
+                            acc = Atk.get_focus_object ();
+                        }
+
+                        if (!get_acc_geometry (acc, out x, out y, out w, out h)) {
+                            return false;
+                        }
+                    }
+
+                    stdout.printf ("focus_in %p %s %d %d %d %d\n", this,
+                                   window.is_visible ().to_string (), x, y, w, h);
+
+                    try {
+                        keyboard.show ();
+                        keyboard.set_entry_location (x, y, w, h);
+                    } catch (IOError e) {
+                        stderr.printf ("%s\n", e.message);
+                    }
+                    return false;
+                });
+        }
+                
+
         public override void focus_out () {
+            stdout.printf ("focus_out %p %s\n", this,
+                           window.is_visible ().to_string ());
             try {
                 keyboard.hide ();
             } catch (IOError e) {
@@ -41,6 +118,7 @@ namespace Caribou {
 
         public override void set_client_window (Gdk.Window window) {
             this.window = window;
+
             try {
                 keyboard = Bus.get_proxy_sync (BusType.SESSION,
                                                "org.gnome.Caribou.Antler",
@@ -48,7 +126,7 @@ namespace Caribou {
             } catch (Error e) {
                 stderr.printf ("%s\n", e.message);
             }
-            stdout.printf ("set_client_window\n");
+            stdout.printf ("set_client_window %p %p\n", this, window);
         }
     }
 }
\ No newline at end of file
diff --git a/im/gtk3/vapi-fixes.vapi b/im/gtk3/vapi-fixes.vapi
new file mode 100644
index 0000000..7b21d78
--- /dev/null
+++ b/im/gtk3/vapi-fixes.vapi
@@ -0,0 +1,10 @@
+using Atk;
+
+[CCode (cprefix = "Atk", lower_case_cprefix = "atk_", cheader_filename = "atk/atk.h")]
+
+namespace Atk {
+    [CCode (cname = "atk_component_get_extents")]
+    public void component_get_extents (Atk.Component component,
+                                       out int x, out int y, out int w, out int h,
+                                       Atk.CoordType coord_type);
+}
\ No newline at end of file



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]