summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorJohn-Mark Bell <jmb@netsurf-browser.org>2014-02-17 00:21:49 +0000
committerJohn-Mark Bell <jmb@netsurf-browser.org>2014-02-17 00:21:49 +0000
commitb928095652a00bf579d8d724262b856f82a57a0f (patch)
tree25c120f2abc064944d97f1a843cea7b056e3e36f /gtk
parentc47a497bca10e2fce6fd2f458e9b5b9f6992062d (diff)
downloadnetsurf-b928095652a00bf579d8d724262b856f82a57a0f.tar.gz
netsurf-b928095652a00bf579d8d724262b856f82a57a0f.tar.bz2
GTK: add some support for input methods.
We do not currently support pre-edit texts, or retrieving/modifying text surrounding the caret. This does, at least, finally allow the use of dead keys during text input, but probably is insufficient for useful input of CJKV &c.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/treeview.c68
-rw-r--r--gtk/treeview.h10
-rw-r--r--gtk/window.c50
3 files changed, 109 insertions, 19 deletions
diff --git a/gtk/treeview.c b/gtk/treeview.c
index 2a4732a87..c99e9fd43 100644
--- a/gtk/treeview.c
+++ b/gtk/treeview.c
@@ -35,12 +35,14 @@
#include "gtk/plotters.h"
#include "gtk/treeview.h"
#include "utils/log.h"
+#include "utils/utf8.h"
#include "utils/utils.h"
struct nsgtk_treeview {
GtkWindow *window;
GtkScrolledWindow *scrolled;
GtkDrawingArea *drawing_area;
+ GtkIMContext *input_method;
bool mouse_pressed;
int mouse_pressed_x;
int mouse_pressed_y;
@@ -52,6 +54,7 @@ struct nsgtk_treeview {
void nsgtk_treeview_destroy(struct nsgtk_treeview *tv)
{
tree_delete(tv->tree);
+ g_object_unref(tv->input_method);
gtk_widget_destroy(GTK_WIDGET(tv->window));
free(tv);
}
@@ -206,12 +209,14 @@ void nsgtk_tree_window_hide(GtkWidget *widget, gpointer g)
{
}
-gboolean nsgtk_tree_window_button_press_event(GtkWidget *widget,
+static gboolean
+nsgtk_tree_window_button_press_event(GtkWidget *widget,
GdkEventButton *event, gpointer g)
{
struct nsgtk_treeview *tw = g;
struct tree *tree = tw->tree;
+ gtk_im_context_reset(tw->input_method);
gtk_widget_grab_focus(GTK_WIDGET(tw->drawing_area));
tw->mouse_pressed = true;
@@ -243,7 +248,8 @@ gboolean nsgtk_tree_window_button_press_event(GtkWidget *widget,
return TRUE;
}
-gboolean nsgtk_tree_window_button_release_event(GtkWidget *widget,
+static gboolean
+nsgtk_tree_window_button_release_event(GtkWidget *widget,
GdkEventButton *event, gpointer g)
{
bool shift = event->state & GDK_SHIFT_MASK;
@@ -307,7 +313,8 @@ gboolean nsgtk_tree_window_button_release_event(GtkWidget *widget,
return TRUE;
}
-gboolean nsgtk_tree_window_motion_notify_event(GtkWidget *widget,
+static gboolean
+nsgtk_tree_window_motion_notify_event(GtkWidget *widget,
GdkEventMotion *event, gpointer g)
{
bool shift = event->state & GDK_SHIFT_MASK;
@@ -369,7 +376,8 @@ gboolean nsgtk_tree_window_motion_notify_event(GtkWidget *widget,
}
-gboolean nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
+static gboolean
+nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
gpointer g)
{
struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g;
@@ -381,6 +389,9 @@ gboolean nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
GtkAdjustment *scroll = NULL;
gdouble hpage, vpage;
+ if (gtk_im_context_filter_keypress(tw->input_method, event))
+ return TRUE;
+
nskey = gtk_gui_gdkkey_to_nskey(event);
if (tree_keypress(tree, nskey) == true)
@@ -473,6 +484,32 @@ gboolean nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
return TRUE;
}
+static gboolean
+nsgtk_tree_window_keyrelease_event(GtkWidget *widget, GdkEventKey *event,
+ gpointer g)
+{
+ struct nsgtk_treeview *tw = (struct nsgtk_treeview *) g;
+
+ return gtk_im_context_filter_keypress(tw->input_method, event);
+}
+
+static void
+nsgtk_tree_window_input_method_commit(GtkIMContext *ctx,
+ const gchar *str, gpointer data)
+{
+ struct nsgtk_treeview *tw = (struct nsgtk_treeview *) data;
+ size_t len = strlen(str), offset = 0;
+
+ while (offset < len) {
+ uint32_t nskey = utf8_to_ucs4(str + offset, len - offset);
+
+ tree_keypress(tw->tree, nskey);
+
+ offset = utf8_next(str, len, offset);
+ }
+}
+
+
static const struct treeview_table nsgtk_tree_callbacks = {
.redraw_request = nsgtk_tree_redraw_request,
.resized = nsgtk_tree_resized,
@@ -498,6 +535,7 @@ struct nsgtk_treeview *nsgtk_treeview_create(unsigned int flags,
tv->window = window;
tv->scrolled = scrolled;
tv->drawing_area = drawing_area;
+ tv->input_method = gtk_im_multicontext_new();
tv->tree = tree_create(flags, &nsgtk_tree_callbacks, tv);
tv->mouse_state = 0;
tv->mouse_pressed = false;
@@ -510,17 +548,31 @@ struct nsgtk_treeview *nsgtk_treeview_create(unsigned int flags,
#define CONNECT(obj, sig, callback, ptr) \
g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
- CONNECT(drawing_area, "button_press_event",
+ CONNECT(drawing_area, "button-press-event",
nsgtk_tree_window_button_press_event,
tv);
- CONNECT(drawing_area, "button_release_event",
+ CONNECT(drawing_area, "button-release-event",
nsgtk_tree_window_button_release_event,
tv);
- CONNECT(drawing_area, "motion_notify_event",
+ CONNECT(drawing_area, "motion-notify-event",
nsgtk_tree_window_motion_notify_event,
tv);
- CONNECT(drawing_area, "key_press_event",
+ CONNECT(drawing_area, "key-press-event",
nsgtk_tree_window_keypress_event,
tv);
+ CONNECT(drawing_area, "key-release-event",
+ nsgtk_tree_window_keyrelease_event,
+ tv);
+
+
+ /* input method */
+ gtk_im_context_set_client_window(tv->input_method,
+ nsgtk_widget_get_window(GTK_WIDGET(tv->window)));
+ gtk_im_context_set_use_preedit(tv->input_method, FALSE);
+ /* input method signals */
+ CONNECT(tv->input_method, "commit",
+ nsgtk_tree_window_input_method_commit,
+ tv);
+
return tv;
}
diff --git a/gtk/treeview.h b/gtk/treeview.h
index a0acbd49c..ad8180f33 100644
--- a/gtk/treeview.h
+++ b/gtk/treeview.h
@@ -33,16 +33,6 @@ void nsgtk_treeview_destroy(struct nsgtk_treeview *tv);
struct tree *nsgtk_treeview_get_tree(struct nsgtk_treeview *tv);
-gboolean nsgtk_tree_window_expose_event(GtkWidget *, GdkEventExpose *,
- gpointer g);
void nsgtk_tree_window_hide(GtkWidget *widget, gpointer g);
-gboolean nsgtk_tree_window_button_press_event(GtkWidget *widget,
- GdkEventButton *event, gpointer g);
-gboolean nsgtk_tree_window_button_release_event(GtkWidget *widget,
- GdkEventButton *event, gpointer g);
-gboolean nsgtk_tree_window_motion_notify_event(GtkWidget *widget,
- GdkEventMotion *event, gpointer g);
-gboolean nsgtk_tree_window_keypress_event(GtkWidget *widget, GdkEventKey *event,
- gpointer g);
#endif /*__NSGTK_TREEVIEW_H__*/
diff --git a/gtk/window.c b/gtk/window.c
index 038622d19..2da346b33 100644
--- a/gtk/window.c
+++ b/gtk/window.c
@@ -27,6 +27,7 @@
#include <gdk-pixbuf/gdk-pixdata.h>
#include "utils/log.h"
+#include "utils/utf8.h"
#include "utils/utils.h"
#include "utils/nsoption.h"
#include "content/hlcache.h"
@@ -105,6 +106,9 @@ struct gui_window {
/** The icon this window should have */
GdkPixbuf *icon;
+ /** The input method to use with this window */
+ GtkIMContext *input_method;
+
/** list for cleanup */
struct gui_window *next, *prev;
};
@@ -315,6 +319,7 @@ static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
{
struct gui_window *g = data;
+ gtk_im_context_reset(g->input_method);
gtk_widget_grab_focus(GTK_WIDGET(g->layout));
gtk_widget_hide(GTK_WIDGET(nsgtk_scaffolding_history_window(
g->scaffold)->window));
@@ -490,7 +495,12 @@ static gboolean nsgtk_window_keypress_event(GtkWidget *widget,
GdkEventKey *event, gpointer data)
{
struct gui_window *g = data;
- uint32_t nskey = gtk_gui_gdkkey_to_nskey(event);
+ uint32_t nskey;
+
+ if (gtk_im_context_filter_keypress(g->input_method, event))
+ return TRUE;
+
+ nskey = gtk_gui_gdkkey_to_nskey(event);
if (browser_window_key_press(g->bw, nskey))
return TRUE;
@@ -598,6 +608,31 @@ static gboolean nsgtk_window_keypress_event(GtkWidget *widget,
return TRUE;
}
+static gboolean nsgtk_window_keyrelease_event(GtkWidget *widget,
+ GdkEventKey *event, gpointer data)
+{
+ struct gui_window *g = data;
+
+ return gtk_im_context_filter_keypress(g->input_method, event);
+}
+
+
+static void nsgtk_window_input_method_commit(GtkIMContext *ctx,
+ const gchar *str, gpointer data)
+{
+ struct gui_window *g = data;
+ size_t len = strlen(str), offset = 0;
+
+ while (offset < len) {
+ uint32_t nskey = utf8_to_ucs4(str + offset, len - offset);
+
+ browser_window_key_press(g->bw, nskey);
+
+ offset = utf8_next(str, len, offset);
+ }
+}
+
+
static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget,
GtkAllocation *allocation, gpointer data)
{
@@ -658,6 +693,8 @@ static void window_destroy(GtkWidget *widget, gpointer data)
struct gui_window *gw = data;
browser_window_destroy(gw->bw);
+
+ g_object_unref(gw->input_method);
}
/* Core interface documented in desktop/gui.h to create a gui_window */
@@ -720,6 +757,7 @@ gui_window_create(struct browser_window *bw,
g->layout = GTK_LAYOUT(gtk_builder_get_object(xml, "layout"));
g->status_bar = GTK_LABEL(gtk_builder_get_object(xml, "status_bar"));
g->paned = GTK_PANED(gtk_builder_get_object(xml, "hpaned1"));
+ g->input_method = gtk_im_multicontext_new();
/* add new gui window to global list (push_top) */
@@ -763,6 +801,8 @@ gui_window_create(struct browser_window *bw,
nsgtk_window_button_release_event, g);
CONNECT(g->layout, "key-press-event",
nsgtk_window_keypress_event, g);
+ CONNECT(g->layout, "key-release-event",
+ nsgtk_window_keyrelease_event, g);
CONNECT(g->layout, "size-allocate",
nsgtk_window_size_allocate_event, g);
CONNECT(g->layout, "scroll-event",
@@ -779,6 +819,14 @@ gui_window_create(struct browser_window *bw,
CONNECT(g->container, "destroy",
window_destroy, g);
+ /* input method */
+ gtk_im_context_set_client_window(g->input_method,
+ nsgtk_layout_get_bin_window(g->layout));
+ gtk_im_context_set_use_preedit(g->input_method, FALSE);
+ /* input method signals */
+ CONNECT(g->input_method, "commit",
+ nsgtk_window_input_method_commit, g);
+
/* add the tab container to the scaffold notebook */
switch (temp_open_background) {
case -1: