summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/Makefile.am9
-rw-r--r--modules/gtk2/Makefile.am33
l---------modules/gtk2/caribou-gtk-modules.vala1
l---------modules/gtk2/caribou-module.c1
l---------modules/gtk2/vapi-fixes.vapi1
-rw-r--r--modules/gtk3/Makefile.am32
-rw-r--r--modules/gtk3/caribou-gtk-modules.vala138
-rw-r--r--modules/gtk3/caribou-module.c21
-rw-r--r--modules/gtk3/vapi-fixes.vapi10
9 files changed, 246 insertions, 0 deletions
diff --git a/modules/Makefile.am b/modules/Makefile.am
new file mode 100644
index 0000000..47ecbb7
--- /dev/null
+++ b/modules/Makefile.am
@@ -0,0 +1,9 @@
+SUBDIRS =
+
+if ENABLE_GTK3_MODULES
+SUBDIRS += gtk3
+endif
+
+if ENABLE_GTK2_MODULES
+SUBDIRS += gtk2
+endif
diff --git a/modules/gtk2/Makefile.am b/modules/gtk2/Makefile.am
new file mode 100644
index 0000000..cff49fd
--- /dev/null
+++ b/modules/gtk2/Makefile.am
@@ -0,0 +1,33 @@
+gtk_modulesdir = @GTK2_MODULES_DIR@
+gtk_modules_LTLIBRARIES = libcaribou.la
+
+libcaribou_la_SOURCES = \
+ caribou-gtk-modules.vala \
+ caribou-module.c \
+ $(NULL)
+
+libcaribou_la_VALAFLAGS = \
+ -h caribou-gtk-modules.h \
+ --vapidir=. \
+ --pkg vapi-fixes \
+ --pkg gtk+-2.0 \
+ -D GTK2 \
+ $(VALAGLAFS)
+
+libcaribou_la_CFLAGS = \
+ @GTK2_CFLAGS@ \
+ -DG_LOG_DOMAIN=\"CARIBOU\" \
+ $(NULL)
+
+libcaribou_la_LIBADD = \
+ @GTK2_LIBS@ \
+ $(NULL)
+
+libcaribou_la_LDFLAGS = \
+ -avoid-version \
+ -module \
+ $(NULL)
+
+EXTRA_DIST = \
+ vapi-fixes.vapi \
+ $(NULL)
diff --git a/modules/gtk2/caribou-gtk-modules.vala b/modules/gtk2/caribou-gtk-modules.vala
new file mode 120000
index 0000000..5b7285b
--- /dev/null
+++ b/modules/gtk2/caribou-gtk-modules.vala
@@ -0,0 +1 @@
+../gtk3/caribou-gtk-modules.vala \ No newline at end of file
diff --git a/modules/gtk2/caribou-module.c b/modules/gtk2/caribou-module.c
new file mode 120000
index 0000000..e08e22e
--- /dev/null
+++ b/modules/gtk2/caribou-module.c
@@ -0,0 +1 @@
+../gtk3/caribou-module.c \ No newline at end of file
diff --git a/modules/gtk2/vapi-fixes.vapi b/modules/gtk2/vapi-fixes.vapi
new file mode 120000
index 0000000..cb1b309
--- /dev/null
+++ b/modules/gtk2/vapi-fixes.vapi
@@ -0,0 +1 @@
+../gtk3/vapi-fixes.vapi \ No newline at end of file
diff --git a/modules/gtk3/Makefile.am b/modules/gtk3/Makefile.am
new file mode 100644
index 0000000..54ef4cc
--- /dev/null
+++ b/modules/gtk3/Makefile.am
@@ -0,0 +1,32 @@
+gtk_modulesdir = @GTK3_MODULES_DIR@
+gtk_modules_LTLIBRARIES = libcaribou.la
+
+libcaribou_la_SOURCES = \
+ caribou-gtk-modules.vala \
+ caribou-module.c \
+ $(NULL)
+
+libcaribou_la_VALAFLAGS = \
+ -h caribou-gtk-modules.h \
+ --vapidir=. \
+ --pkg vapi-fixes \
+ --pkg gtk+-3.0 \
+ $(VALAGLAFS)
+
+libcaribou_la_CFLAGS = \
+ @GTK3_CFLAGS@ \
+ -DG_LOG_DOMAIN=\"CARIBOU\" \
+ $(NULL)
+
+libcaribou_la_LIBADD = \
+ @GTK3_LIBS@ \
+ $(NULL)
+
+libcaribou_la_LDFLAGS = \
+ -avoid-version \
+ -module \
+ $(NULL)
+
+EXTRA_DIST = \
+ vapi-fixes.vapi \
+ $(NULL)
diff --git a/modules/gtk3/caribou-gtk-modules.vala b/modules/gtk3/caribou-gtk-modules.vala
new file mode 100644
index 0000000..bc87737
--- /dev/null
+++ b/modules/gtk3/caribou-gtk-modules.vala
@@ -0,0 +1,138 @@
+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 show (uint32 timestamp) throws IOError;
+ public abstract void hide (uint32 timestamp) throws IOError;
+ }
+
+ class GtkModules {
+ private GLib.List<Gtk.Window> windows;
+ private Keyboard keyboard;
+
+ public GtkModules () {
+ windows = new GLib.List<Gtk.Window>();
+ try {
+ keyboard = Bus.get_proxy_sync (BusType.SESSION,
+ "org.gnome.Caribou.Keyboard",
+ "/org/gnome/Caribou/Keyboard");
+ } catch (Error e) {
+ stderr.printf ("%s\n", e.message);
+ }
+
+ add_tracker ();
+
+ GLib.Timeout.add (60, () => { add_tracker ();
+ return true; });
+ }
+
+ private void add_tracker () {
+ GLib.List<weak Gtk.Window> toplevels;
+
+ toplevels = Gtk.Window.list_toplevels();
+ foreach (Gtk.Window window in toplevels) {
+ if (windows.find(window) == null) {
+ window.notify["has-toplevel-focus"].connect(get_top_level_focus);
+ windows.append(window);
+ }
+ }
+ }
+
+ private void get_top_level_focus (Object obj, ParamSpec prop) {
+ Gtk.Window window = (Gtk.Window) obj;
+ if (window.has_toplevel_focus)
+ focus_tracker (window, window.get_focus());
+ }
+
+ private void focus_tracker (Gtk.Window window, Gtk.Widget? widget) {
+ uint32 timestamp = Gtk.get_current_event_time();
+ if (widget != null && (widget is Gtk.Entry || widget is Gtk.TextView) && widget is Gtk.Editable) {
+ Atk.Object focus_object = widget.get_accessible();
+ Gdk.Window current_window = widget.get_window();
+ int x=0, y=0, w=0, h=0;
+ if (current_window != null && !get_acc_geometry (focus_object, out x, out y, out w, out h)) {
+ get_origin_geometry (current_window, out x, out y, out w, out h);
+ }
+ try {
+ keyboard.show (timestamp);
+ keyboard.set_entry_location (x, y, w, h);
+ } catch (IOError e) {
+ stderr.printf ("%s\n", e.message);
+ }
+ }
+ else {
+ try {
+ keyboard.hide (timestamp);
+ } catch (IOError e) {
+ stderr.printf("%s\n", e.message);
+ }
+ }
+ }
+
+ 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
+ }
+
+ 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 = null;
+
+
+ if (acc.get_role () == Atk.Role.REDUNDANT_OBJECT) {
+ /* It is probably Gecko */
+ child = Atk.get_focus_object ();
+ } else {
+ 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;
+ }
+
+ /* We don't want the keyboard on the paragraph in OOo */
+ if (child.get_role() == Atk.Role.PARAGRAPH)
+ child = child.get_parent();
+
+ Atk.component_get_extents ((Atk.Component) child,
+ out x, out y, out w, out h,
+ Atk.CoordType.SCREEN);
+
+ return true;
+ }
+
+ }
+}
diff --git a/modules/gtk3/caribou-module.c b/modules/gtk3/caribou-module.c
new file mode 100644
index 0000000..228383f
--- /dev/null
+++ b/modules/gtk3/caribou-module.c
@@ -0,0 +1,21 @@
+#include <gtk/gtk.h>
+#include <gtk/gtkimmodule.h>
+#include "caribou-gtk-modules.h"
+#include <stdio.h>
+
+#define CARIBOU_LOCALDIR ""
+
+G_MODULE_EXPORT CaribouGtkModules *
+gtk_module_init (gint *argc, gchar ***argv[]) {
+ CaribouGtkModules *context = caribou_gtk_modules_new ();
+ return context;
+}
+
+G_MODULE_EXPORT const gchar*
+g_module_check_init (GModule *module)
+{
+ return glib_check_version (GLIB_MAJOR_VERSION,
+ GLIB_MINOR_VERSION,
+ 0);
+}
+
diff --git a/modules/gtk3/vapi-fixes.vapi b/modules/gtk3/vapi-fixes.vapi
new file mode 100644
index 0000000..7b21d78
--- /dev/null
+++ b/modules/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