From a309dffd70676eb4c46ed4d9ea2dd65a518c7115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Mon, 14 Sep 2009 01:50:48 +0000 Subject: [PATCH] [GB.GTK] * BUG: Fix input method handling. * NEW: Application_KeyPress global event handler has been implemented. git-svn-id: svn://localhost/gambas/trunk@2335 867c0c6c-44f3-4631-809d-bfa615b0a4ec --- gb.gtk/src/gapplication.cpp | 60 ++++++++++++++++++++++++------------- gb.gtk/src/gapplication.h | 2 ++ gb.gtk/src/gkey.h | 4 +-- gb.gtk/src/gtextarea.cpp | 1 - gb.gtk/src/gtextbox.cpp | 2 -- gb.gtk/src/gtree.cpp | 2 +- gb.gtk/src/main.cpp | 20 ++++++++++--- gb.qt4/src/main.cpp | 40 ++++++++++++++++++------- 8 files changed, 91 insertions(+), 40 deletions(-) diff --git a/gb.gtk/src/gapplication.cpp b/gb.gtk/src/gapplication.cpp index f1e612ee7..2cf6f0733 100644 --- a/gb.gtk/src/gapplication.cpp +++ b/gb.gtk/src/gapplication.cpp @@ -36,6 +36,8 @@ #include "gmouse.h" #include "gmainwindow.h" +//#define DEBUG_IM 1 + /************************************************************************* gKey @@ -46,7 +48,7 @@ bool gKey::_valid = false; bool gKey::_no_input_method = false; GdkEventKey gKey::_event; GtkIMContext *gKey::_im_context = NULL; -GtkWidget *gKey::_im_widget = NULL; +gControl *gKey::_im_control = NULL; char *_im_text = NULL; const char *gKey::text() @@ -117,7 +119,7 @@ void gKey::disable() g_free(_event.string); } -bool gKey::enable(GtkWidget *widget, GdkEventKey *event) +bool gKey::enable(gControl *control, GdkEventKey *event) { bool filter; @@ -130,11 +132,15 @@ bool gKey::enable(GtkWidget *widget, GdkEventKey *event) _valid = true; _event = *event; - if (_event.type == GDK_KEY_PRESS && !_no_input_method && widget == _im_widget) + if (_event.type == GDK_KEY_PRESS && !_no_input_method && control == _im_control) { - //fprintf(stderr, "gKey::enable: event->string = '%s'\n", event->string); + #if DEBUG_IM + fprintf(stderr, "gKey::enable: event->string = '%s'\n", event->string); + #endif filter = gtk_im_context_filter_keypress(_im_context, &_event); - //fprintf(stderr, "gKey::enable: filter -> %d event->string = '%s'\n", filter, event->string); + #if DEBUG_IM + fprintf(stderr, "gKey::enable: filter -> %d event->string = '%s'\n", filter, event->string); + #endif } else filter = false; @@ -142,14 +148,17 @@ bool gKey::enable(GtkWidget *widget, GdkEventKey *event) if (filter && _im_text) { _event.string = g_strdup(_im_text); - filter = false; + _event.keyval = 0; + filter = false; } else _event.string = g_strdup(_event.string); if (!filter) { + //#if DEBUG_IM //fprintf(stderr, "gKey::enable: gtk_im_context_reset\n"); + //#endif //gtk_im_context_reset(_im_context); if (_im_text) { @@ -164,7 +173,9 @@ bool gKey::enable(GtkWidget *widget, GdkEventKey *event) static void cb_im_commit(GtkIMContext *context, const gchar *str, gpointer pointer) { - //fprintf(stderr, "cb_im_commit: %s\n", str); + #if DEBUG_IM + fprintf(stderr, "cb_im_commit: %s\n", str); + #endif if (_im_text) g_free(_im_text); @@ -188,30 +199,34 @@ void gKey::exit() void gKey::setActiveControl(gControl *control) { - if (_im_widget) + if (_im_control) { - //fprintf(stderr, "gtm_im_context_focus_out\n"); if (!_no_input_method) { + #if DEBUG_IM + fprintf(stderr, "gtm_im_context_focus_out\n"); + #endif gtk_im_context_set_client_window (_im_context, 0); gtk_im_context_focus_out(_im_context); } - _im_widget = NULL; + _im_control = NULL; _no_input_method = false; } if (control) { - _im_widget = control->widget; + _im_control = control; _no_input_method = control->noInputMethod(); if (!_no_input_method) { - gtk_im_context_set_client_window (_im_context, _im_widget->window); + gtk_im_context_set_client_window (_im_context, _im_control->widget->window); gtk_im_context_focus_in(_im_context); gtk_im_context_reset(_im_context); - } - //fprintf(stderr, "gtm_im_context_focus_in\n"); + #if DEBUG_IM + fprintf(stderr, "gtm_im_context_focus_in\n"); + #endif + } } } @@ -416,11 +431,15 @@ static void gambas_handle_event(GdkEvent *event) control = gDesktop::activeControl(); - gKey::enable(widget, &event->key); - if (control->onKeyEvent) + if (!gKey::enable(control, &event->key)) { - //fprintf(stderr, "gEvent_KeyPress on %p %s\n", control, control->name()); - cancel = control->onKeyEvent(control, gEvent_KeyPress); + if (gApplication::onKeyEvent) + cancel = gApplication::onKeyEvent(gEvent_KeyPress); + if (!cancel && control->onKeyEvent) + { + //fprintf(stderr, "gEvent_KeyPress on %p %s\n", control, control->name()); + cancel = control->onKeyEvent(control, gEvent_KeyPress); + } } gKey::disable(); @@ -459,8 +478,8 @@ static void gambas_handle_event(GdkEvent *event) control = gDesktop::activeControl(); - gKey::enable(widget, &event->key); - control->emit(SIGNAL(control->onKeyEvent), gEvent_KeyRelease); + if (!gKey::enable(control, &event->key)) + control->emit(SIGNAL(control->onKeyEvent), gEvent_KeyRelease); gKey::disable(); if (event->key.keyval == GDK_Escape) @@ -505,6 +524,7 @@ void *gApplication::_loop_owner = 0; GtkWindowGroup *gApplication::_group = NULL; gControl *gApplication::_enter = NULL; gControl *gApplication::_leave = NULL; +bool (*gApplication::onKeyEvent)(int) = NULL; GtkTooltips* gApplication::tipHandle() { diff --git a/gb.gtk/src/gapplication.h b/gb.gtk/src/gapplication.h index fc002e8c6..7373d6216 100644 --- a/gb.gtk/src/gapplication.h +++ b/gb.gtk/src/gapplication.h @@ -63,6 +63,8 @@ public: static GtkWindowGroup *enterGroup(); static void exitGroup(GtkWindowGroup *oldGroup); + static bool (*onKeyEvent)(int type); + //"Private" static GtkTooltips *tipHandle(); static bool _busy; diff --git a/gb.gtk/src/gkey.h b/gb.gtk/src/gkey.h index 81599bf25..73069fa63 100644 --- a/gb.gtk/src/gkey.h +++ b/gb.gtk/src/gkey.h @@ -40,7 +40,7 @@ public: //"Private" static void disable(); - static bool enable(GtkWidget *w, GdkEventKey *e); + static bool enable(gControl *control, GdkEventKey *e); static void init(); static void exit(); @@ -50,7 +50,7 @@ private: static GdkEventKey _event; static bool _valid; static GtkIMContext *_im_context; - static GtkWidget *_im_widget; + static gControl *_im_control; static bool _no_input_method; }; diff --git a/gb.gtk/src/gtextarea.cpp b/gb.gtk/src/gtextarea.cpp index 044dbed09..e7762e002 100644 --- a/gb.gtk/src/gtextarea.cpp +++ b/gb.gtk/src/gtextarea.cpp @@ -76,7 +76,6 @@ gTextArea::gTextArea(gContainer *parent) : gControl(parent) have_cursor = true; use_base = true; - no_input_method = true; onChange = 0; onCursor = 0; diff --git a/gb.gtk/src/gtextbox.cpp b/gb.gtk/src/gtextbox.cpp index 3f3755c46..2f290eeae 100644 --- a/gb.gtk/src/gtextbox.cpp +++ b/gb.gtk/src/gtextbox.cpp @@ -56,8 +56,6 @@ gTextBox::gTextBox(gContainer *parent, bool combo) : gControl(parent) initEntry(); } - no_input_method = true; - onChange = NULL; onActivate = NULL; } diff --git a/gb.gtk/src/gtree.cpp b/gb.gtk/src/gtree.cpp index b2846e2b0..9a1b26a7d 100644 --- a/gb.gtk/src/gtree.cpp +++ b/gb.gtk/src/gtree.cpp @@ -1263,7 +1263,7 @@ void gTree::setSorted(bool v) return; _sorted = v; - _sort_column = v ? (view ? 0 : 1) : -1; + _sort_column = v ? 0 : -1; updateSort(); } diff --git a/gb.gtk/src/main.cpp b/gb.gtk/src/main.cpp index 6038ec768..40f998c3d 100644 --- a/gb.gtk/src/main.cpp +++ b/gb.gtk/src/main.cpp @@ -81,12 +81,12 @@ static void my_wait(int duration); static void my_post(void); static int my_loop(); static void my_watch(int fd, int type, void *callback, intptr_t param); -bool post_Check=false; - - -int MAIN_scale = 8; +static bool post_Check=false; +static bool _application_keypress = false; +static GB_FUNCTION _application_keypress_func; +int MAIN_scale = 0; extern "C" { @@ -291,6 +291,12 @@ void my_quit (void) } +static bool global_key_event_handler(int type) +{ + GB.Call(&_application_keypress_func, 0, FALSE); + return GB.Stopped(); +} + static void my_main(int *argc, char **argv) { gApplication::init(argc, &argv); @@ -300,6 +306,12 @@ static void my_main(int *argc, char **argv) #ifdef GDK_WINDOWING_X11 X11_init(gdk_x11_display_get_xdisplay(gdk_display_get_default()), gdk_x11_get_default_root_xwindow()); #endif + + if (GB.GetFunction(&_application_keypress_func, (void *)GB.FindClass(GB.Application.Startup()), "Application_KeyPress", "", "") == 0) + { + _application_keypress = true; + gApplication::onKeyEvent = global_key_event_handler; + } } /*static void raise_timer(GB_TIMER *timer) diff --git a/gb.qt4/src/main.cpp b/gb.qt4/src/main.cpp index e0ca7667e..354248035 100644 --- a/gb.qt4/src/main.cpp +++ b/gb.qt4/src/main.cpp @@ -313,24 +313,44 @@ MyApplication::MyApplication(int &argc, char **argv) static bool QT_EventFilter(QEvent *e) { - QKeyEvent *kevent = (QKeyEvent *)e; bool cancel; - + if (!_application_keypress) return false; - - CKEY_clear(true); + + if (e->type() == QEvent::KeyPress) + { + QKeyEvent *kevent = (QKeyEvent *)e; + + CKEY_clear(true); - GB.FreeString(&CKEY_info.text); - GB.NewString(&CKEY_info.text, QT_ToUTF8(kevent->text()), 0); - CKEY_info.state = kevent->modifiers(); - CKEY_info.code = kevent->key(); + GB.FreeString(&CKEY_info.text); + GB.NewString(&CKEY_info.text, QT_ToUTF8(kevent->text()), 0); + CKEY_info.state = kevent->modifiers(); + CKEY_info.code = kevent->key(); + + } + else if (e->type() == QEvent::InputMethod) + { + QInputMethodEvent *imevent = (QInputMethodEvent *)e; + + if (!imevent->commitString().isEmpty()) + { + CKEY_clear(true); + + GB.FreeString(&CKEY_info.text); + //qDebug("IMEnd: %s", imevent->text().latin1()); + GB.NewString(&CKEY_info.text, QT_ToUTF8(imevent->commitString()), 0); + CKEY_info.state = 0; + CKEY_info.code = 0; + } + } GB.Call(&_application_keypress_func, 0, FALSE); cancel = GB.Stopped(); CKEY_clear(false); - + return cancel; } @@ -346,7 +366,7 @@ bool MyApplication::eventFilter(QObject *o, QEvent *e) { if (o->isWidgetType()) { - if (e->type() == QEvent::KeyPress) + if ((e->spontaneous() && e->type() == QEvent::KeyPress) || e->type() == QEvent::InputMethod) { if (QT_EventFilter(e)) return true;