[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
This commit is contained in:
parent
550ead384c
commit
a309dffd70
8 changed files with 91 additions and 40 deletions
|
@ -36,6 +36,8 @@
|
||||||
#include "gmouse.h"
|
#include "gmouse.h"
|
||||||
#include "gmainwindow.h"
|
#include "gmainwindow.h"
|
||||||
|
|
||||||
|
//#define DEBUG_IM 1
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
||||||
gKey
|
gKey
|
||||||
|
@ -46,7 +48,7 @@ bool gKey::_valid = false;
|
||||||
bool gKey::_no_input_method = false;
|
bool gKey::_no_input_method = false;
|
||||||
GdkEventKey gKey::_event;
|
GdkEventKey gKey::_event;
|
||||||
GtkIMContext *gKey::_im_context = NULL;
|
GtkIMContext *gKey::_im_context = NULL;
|
||||||
GtkWidget *gKey::_im_widget = NULL;
|
gControl *gKey::_im_control = NULL;
|
||||||
char *_im_text = NULL;
|
char *_im_text = NULL;
|
||||||
|
|
||||||
const char *gKey::text()
|
const char *gKey::text()
|
||||||
|
@ -117,7 +119,7 @@ void gKey::disable()
|
||||||
g_free(_event.string);
|
g_free(_event.string);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gKey::enable(GtkWidget *widget, GdkEventKey *event)
|
bool gKey::enable(gControl *control, GdkEventKey *event)
|
||||||
{
|
{
|
||||||
bool filter;
|
bool filter;
|
||||||
|
|
||||||
|
@ -130,11 +132,15 @@ bool gKey::enable(GtkWidget *widget, GdkEventKey *event)
|
||||||
_valid = true;
|
_valid = true;
|
||||||
_event = *event;
|
_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);
|
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
|
else
|
||||||
filter = false;
|
filter = false;
|
||||||
|
@ -142,14 +148,17 @@ bool gKey::enable(GtkWidget *widget, GdkEventKey *event)
|
||||||
if (filter && _im_text)
|
if (filter && _im_text)
|
||||||
{
|
{
|
||||||
_event.string = g_strdup(_im_text);
|
_event.string = g_strdup(_im_text);
|
||||||
filter = false;
|
_event.keyval = 0;
|
||||||
|
filter = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_event.string = g_strdup(_event.string);
|
_event.string = g_strdup(_event.string);
|
||||||
|
|
||||||
if (!filter)
|
if (!filter)
|
||||||
{
|
{
|
||||||
|
//#if DEBUG_IM
|
||||||
//fprintf(stderr, "gKey::enable: gtk_im_context_reset\n");
|
//fprintf(stderr, "gKey::enable: gtk_im_context_reset\n");
|
||||||
|
//#endif
|
||||||
//gtk_im_context_reset(_im_context);
|
//gtk_im_context_reset(_im_context);
|
||||||
if (_im_text)
|
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)
|
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)
|
if (_im_text)
|
||||||
g_free(_im_text);
|
g_free(_im_text);
|
||||||
|
@ -188,30 +199,34 @@ void gKey::exit()
|
||||||
|
|
||||||
void gKey::setActiveControl(gControl *control)
|
void gKey::setActiveControl(gControl *control)
|
||||||
{
|
{
|
||||||
if (_im_widget)
|
if (_im_control)
|
||||||
{
|
{
|
||||||
//fprintf(stderr, "gtm_im_context_focus_out\n");
|
|
||||||
if (!_no_input_method)
|
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_set_client_window (_im_context, 0);
|
||||||
gtk_im_context_focus_out(_im_context);
|
gtk_im_context_focus_out(_im_context);
|
||||||
}
|
}
|
||||||
_im_widget = NULL;
|
_im_control = NULL;
|
||||||
_no_input_method = false;
|
_no_input_method = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (control)
|
if (control)
|
||||||
{
|
{
|
||||||
_im_widget = control->widget;
|
_im_control = control;
|
||||||
_no_input_method = control->noInputMethod();
|
_no_input_method = control->noInputMethod();
|
||||||
|
|
||||||
if (!_no_input_method)
|
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_focus_in(_im_context);
|
||||||
gtk_im_context_reset(_im_context);
|
gtk_im_context_reset(_im_context);
|
||||||
|
#if DEBUG_IM
|
||||||
|
fprintf(stderr, "gtm_im_context_focus_in\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
//fprintf(stderr, "gtm_im_context_focus_in\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,11 +431,15 @@ static void gambas_handle_event(GdkEvent *event)
|
||||||
|
|
||||||
control = gDesktop::activeControl();
|
control = gDesktop::activeControl();
|
||||||
|
|
||||||
gKey::enable(widget, &event->key);
|
if (!gKey::enable(control, &event->key))
|
||||||
if (control->onKeyEvent)
|
|
||||||
{
|
{
|
||||||
//fprintf(stderr, "gEvent_KeyPress on %p %s\n", control, control->name());
|
if (gApplication::onKeyEvent)
|
||||||
cancel = control->onKeyEvent(control, gEvent_KeyPress);
|
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();
|
gKey::disable();
|
||||||
|
|
||||||
|
@ -459,8 +478,8 @@ static void gambas_handle_event(GdkEvent *event)
|
||||||
|
|
||||||
control = gDesktop::activeControl();
|
control = gDesktop::activeControl();
|
||||||
|
|
||||||
gKey::enable(widget, &event->key);
|
if (!gKey::enable(control, &event->key))
|
||||||
control->emit(SIGNAL(control->onKeyEvent), gEvent_KeyRelease);
|
control->emit(SIGNAL(control->onKeyEvent), gEvent_KeyRelease);
|
||||||
gKey::disable();
|
gKey::disable();
|
||||||
|
|
||||||
if (event->key.keyval == GDK_Escape)
|
if (event->key.keyval == GDK_Escape)
|
||||||
|
@ -505,6 +524,7 @@ void *gApplication::_loop_owner = 0;
|
||||||
GtkWindowGroup *gApplication::_group = NULL;
|
GtkWindowGroup *gApplication::_group = NULL;
|
||||||
gControl *gApplication::_enter = NULL;
|
gControl *gApplication::_enter = NULL;
|
||||||
gControl *gApplication::_leave = NULL;
|
gControl *gApplication::_leave = NULL;
|
||||||
|
bool (*gApplication::onKeyEvent)(int) = NULL;
|
||||||
|
|
||||||
GtkTooltips* gApplication::tipHandle()
|
GtkTooltips* gApplication::tipHandle()
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,6 +63,8 @@ public:
|
||||||
static GtkWindowGroup *enterGroup();
|
static GtkWindowGroup *enterGroup();
|
||||||
static void exitGroup(GtkWindowGroup *oldGroup);
|
static void exitGroup(GtkWindowGroup *oldGroup);
|
||||||
|
|
||||||
|
static bool (*onKeyEvent)(int type);
|
||||||
|
|
||||||
//"Private"
|
//"Private"
|
||||||
static GtkTooltips *tipHandle();
|
static GtkTooltips *tipHandle();
|
||||||
static bool _busy;
|
static bool _busy;
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
|
|
||||||
//"Private"
|
//"Private"
|
||||||
static void disable();
|
static void disable();
|
||||||
static bool enable(GtkWidget *w, GdkEventKey *e);
|
static bool enable(gControl *control, GdkEventKey *e);
|
||||||
static void init();
|
static void init();
|
||||||
static void exit();
|
static void exit();
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ private:
|
||||||
static GdkEventKey _event;
|
static GdkEventKey _event;
|
||||||
static bool _valid;
|
static bool _valid;
|
||||||
static GtkIMContext *_im_context;
|
static GtkIMContext *_im_context;
|
||||||
static GtkWidget *_im_widget;
|
static gControl *_im_control;
|
||||||
static bool _no_input_method;
|
static bool _no_input_method;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,6 @@ gTextArea::gTextArea(gContainer *parent) : gControl(parent)
|
||||||
|
|
||||||
have_cursor = true;
|
have_cursor = true;
|
||||||
use_base = true;
|
use_base = true;
|
||||||
no_input_method = true;
|
|
||||||
|
|
||||||
onChange = 0;
|
onChange = 0;
|
||||||
onCursor = 0;
|
onCursor = 0;
|
||||||
|
|
|
@ -56,8 +56,6 @@ gTextBox::gTextBox(gContainer *parent, bool combo) : gControl(parent)
|
||||||
initEntry();
|
initEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
no_input_method = true;
|
|
||||||
|
|
||||||
onChange = NULL;
|
onChange = NULL;
|
||||||
onActivate = NULL;
|
onActivate = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1263,7 +1263,7 @@ void gTree::setSorted(bool v)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_sorted = v;
|
_sorted = v;
|
||||||
_sort_column = v ? (view ? 0 : 1) : -1;
|
_sort_column = v ? 0 : -1;
|
||||||
updateSort();
|
updateSort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,12 +81,12 @@ static void my_wait(int duration);
|
||||||
static void my_post(void);
|
static void my_post(void);
|
||||||
static int my_loop();
|
static int my_loop();
|
||||||
static void my_watch(int fd, int type, void *callback, intptr_t param);
|
static void my_watch(int fd, int type, void *callback, intptr_t param);
|
||||||
bool post_Check=false;
|
static bool post_Check=false;
|
||||||
|
|
||||||
|
|
||||||
int MAIN_scale = 8;
|
|
||||||
|
|
||||||
|
static bool _application_keypress = false;
|
||||||
|
static GB_FUNCTION _application_keypress_func;
|
||||||
|
|
||||||
|
int MAIN_scale = 0;
|
||||||
|
|
||||||
extern "C"
|
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)
|
static void my_main(int *argc, char **argv)
|
||||||
{
|
{
|
||||||
gApplication::init(argc, &argv);
|
gApplication::init(argc, &argv);
|
||||||
|
@ -300,6 +306,12 @@ static void my_main(int *argc, char **argv)
|
||||||
#ifdef GDK_WINDOWING_X11
|
#ifdef GDK_WINDOWING_X11
|
||||||
X11_init(gdk_x11_display_get_xdisplay(gdk_display_get_default()), gdk_x11_get_default_root_xwindow());
|
X11_init(gdk_x11_display_get_xdisplay(gdk_display_get_default()), gdk_x11_get_default_root_xwindow());
|
||||||
#endif
|
#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)
|
/*static void raise_timer(GB_TIMER *timer)
|
||||||
|
|
|
@ -313,18 +313,38 @@ MyApplication::MyApplication(int &argc, char **argv)
|
||||||
|
|
||||||
static bool QT_EventFilter(QEvent *e)
|
static bool QT_EventFilter(QEvent *e)
|
||||||
{
|
{
|
||||||
QKeyEvent *kevent = (QKeyEvent *)e;
|
|
||||||
bool cancel;
|
bool cancel;
|
||||||
|
|
||||||
if (!_application_keypress)
|
if (!_application_keypress)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CKEY_clear(true);
|
if (e->type() == QEvent::KeyPress)
|
||||||
|
{
|
||||||
|
QKeyEvent *kevent = (QKeyEvent *)e;
|
||||||
|
|
||||||
GB.FreeString(&CKEY_info.text);
|
CKEY_clear(true);
|
||||||
GB.NewString(&CKEY_info.text, QT_ToUTF8(kevent->text()), 0);
|
|
||||||
CKEY_info.state = kevent->modifiers();
|
GB.FreeString(&CKEY_info.text);
|
||||||
CKEY_info.code = kevent->key();
|
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);
|
GB.Call(&_application_keypress_func, 0, FALSE);
|
||||||
cancel = GB.Stopped();
|
cancel = GB.Stopped();
|
||||||
|
@ -346,7 +366,7 @@ bool MyApplication::eventFilter(QObject *o, QEvent *e)
|
||||||
{
|
{
|
||||||
if (o->isWidgetType())
|
if (o->isWidgetType())
|
||||||
{
|
{
|
||||||
if (e->type() == QEvent::KeyPress)
|
if ((e->spontaneous() && e->type() == QEvent::KeyPress) || e->type() == QEvent::InputMethod)
|
||||||
{
|
{
|
||||||
if (QT_EventFilter(e))
|
if (QT_EventFilter(e))
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue