Keyboard management fixes.
[GB.GTK] * BUG: Fix management of default and cancel buttons shortcuts. * BUG: Workaround the default accelerator management of GTK, so that they are triggered only if no other widget handle the keyboard event. [GB.GTK3] * BUG: Fix management of default and cancel buttons shortcuts. * BUG: Workaround the default accelerator management of GTK, so that they are triggered only if no other widget handle the keyboard event.
This commit is contained in:
parent
38eefd7d21
commit
9c3fc87265
10 changed files with 96 additions and 37 deletions
|
@ -823,14 +823,14 @@ __FOUND_WIDGET:
|
|||
|
||||
if (event->key.keyval)
|
||||
gKey::_last_key_press = event->key.keyval;
|
||||
send_to_window = control->isWindow();
|
||||
send_to_window = false; //control->isWindow();
|
||||
goto __HANDLE_EVENT;
|
||||
|
||||
case GDK_KEY_RELEASE:
|
||||
|
||||
if (event->key.keyval)
|
||||
gKey::_last_key_release = event->key.keyval;
|
||||
send_to_window = control->isWindow();
|
||||
send_to_window = false; //control->isWindow();
|
||||
goto __HANDLE_EVENT;
|
||||
|
||||
default:
|
||||
|
|
|
@ -440,7 +440,7 @@ void gComboBox::setRealForeground(gColor color)
|
|||
}
|
||||
#endif
|
||||
|
||||
int gComboBox::count()
|
||||
int gComboBox::count() const
|
||||
{
|
||||
return tree->rowCount();
|
||||
}
|
||||
|
@ -487,7 +487,7 @@ int gComboBox::length()
|
|||
return gTextBox::length();
|
||||
}
|
||||
|
||||
bool gComboBox::isSorted()
|
||||
bool gComboBox::isSorted() const
|
||||
{
|
||||
return tree->isSorted();
|
||||
}
|
||||
|
@ -718,7 +718,7 @@ int gComboBox::minimumHeight()
|
|||
}
|
||||
|
||||
|
||||
bool gComboBox::isReadOnly()
|
||||
bool gComboBox::isReadOnly() const
|
||||
{
|
||||
return entry == NULL;
|
||||
}
|
||||
|
|
|
@ -33,13 +33,13 @@ public:
|
|||
gComboBox(gContainer *parent);
|
||||
~gComboBox();
|
||||
|
||||
int count();
|
||||
int count() const;
|
||||
int index();
|
||||
char* itemText(int ind);
|
||||
virtual int length();
|
||||
//char** list();
|
||||
virtual bool isReadOnly();
|
||||
bool isSorted();
|
||||
virtual bool isReadOnly() const;
|
||||
bool isSorted() const;
|
||||
virtual char *text();
|
||||
|
||||
void setIndex(int vl);
|
||||
|
|
|
@ -363,6 +363,7 @@ void gControl::initAll(gContainer *parent)
|
|||
_is_button = false;
|
||||
_is_drawingarea = false;
|
||||
_has_native_popup = false;
|
||||
_eat_return_key = false;
|
||||
|
||||
onFinish = NULL;
|
||||
onFocusEvent = NULL;
|
||||
|
|
|
@ -173,6 +173,8 @@ public:
|
|||
bool canFocusOnClick() const;
|
||||
void setCanFocus(bool vl);
|
||||
|
||||
bool eatReturnKey() const { return _eat_return_key; }
|
||||
|
||||
gControl *proxy() const { return _proxy; }
|
||||
bool setProxy(gControl *proxy);
|
||||
|
||||
|
@ -302,7 +304,8 @@ public:
|
|||
unsigned _is_window : 1; // I am a window
|
||||
unsigned _is_button : 1; // I am a button
|
||||
unsigned _is_drawingarea : 1; // I am a drawing area
|
||||
unsigned _has_native_popup : 1; // I have a native popup menu
|
||||
unsigned _has_native_popup : 1; // I have a native popup menu
|
||||
unsigned _eat_return_key : 1; // If the control eats the return key
|
||||
|
||||
void removeParent() { pr = NULL; }
|
||||
void initSignals();
|
||||
|
|
|
@ -445,7 +445,7 @@ bool gKey::raiseEvent(int type, gControl *control, const char *text)
|
|||
bool cancel = false;
|
||||
|
||||
#if DEBUG_IM
|
||||
fprintf(stderr, "gKey::raiseEvent to %p %s\n", control, control->name());
|
||||
fprintf(stderr, "gKey::raiseEvent %s to %p %s\n", type == gEvent_KeyPress ? "KeyPress" : "KeyRelease", control, control->name());
|
||||
#endif
|
||||
|
||||
if (text)
|
||||
|
@ -471,11 +471,19 @@ __KEY_TRY_PROXY:
|
|||
{
|
||||
//fprintf(stderr, "gEvent_KeyPress on %p %s\n", control, control->name());
|
||||
//fprintf(stderr, "onKeyEvent: %p %d %p %s\n", event, type, control, control->name());
|
||||
#if DEBUG_IM
|
||||
fprintf(stderr, "--> %s\n", control->name());
|
||||
#endif
|
||||
cancel = control->onKeyEvent(control, type);
|
||||
}
|
||||
|
||||
if (cancel)
|
||||
{
|
||||
#if DEBUG_IM
|
||||
fprintf(stderr, "--> cancel\n");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if (control->_proxy_for)
|
||||
{
|
||||
|
@ -498,7 +506,7 @@ gboolean gcb_key_event(GtkWidget *widget, GdkEvent *event, gControl *control)
|
|||
bool cancel;
|
||||
|
||||
#if DEBUG_IM
|
||||
fprintf(stderr, "gcb_key_event %s for %p %s / active = %p %s\n", event->type == GDK_KEY_PRESS ? "GDK_KEY_PRESS" : "GDK_KEY_RELEASE", control, control->name(), gApplication::activeControl(), gApplication::activeControl() ? gApplication::activeControl()->name() : "-");
|
||||
fprintf(stderr, "gcb_key_event: %s for %p %s / active = %p %s\n", event->type == GDK_KEY_PRESS ? "GDK_KEY_PRESS" : "GDK_KEY_RELEASE", control, control->name(), gApplication::activeControl(), gApplication::activeControl() ? gApplication::activeControl()->name() : "-");
|
||||
#endif
|
||||
|
||||
/*if (!control->_grab && gApplication::activeControl())
|
||||
|
@ -540,30 +548,39 @@ gboolean gcb_key_event(GtkWidget *widget, GdkEvent *event, gControl *control)
|
|||
if (cancel)
|
||||
return true;
|
||||
|
||||
win = control->window();
|
||||
|
||||
if (event->key.keyval == GDK_Escape)
|
||||
if (type == gEvent_KeyPress)
|
||||
{
|
||||
if (control->_grab)
|
||||
{
|
||||
gApplication::exitLoop(control);
|
||||
return true;
|
||||
}
|
||||
win = control->window();
|
||||
|
||||
if (check_button(win->_cancel))
|
||||
if (event->key.keyval == GDK_Escape)
|
||||
{
|
||||
win->_cancel->setFocus();
|
||||
win->_cancel->animateClick(type == gEvent_KeyRelease);
|
||||
return true;
|
||||
if (control->_grab)
|
||||
{
|
||||
gApplication::exitLoop(control);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (check_button(win->_cancel))
|
||||
{
|
||||
#if DEBUG_IM
|
||||
fprintf(stderr, "gcb_key_event: cancel button\n");
|
||||
#endif
|
||||
win->_cancel->setFocus();
|
||||
win->_cancel->animateClick(type == gEvent_KeyRelease);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event->key.keyval == GDK_Return || event->key.keyval == GDK_KP_Enter)
|
||||
{
|
||||
if (check_button(win->_default))
|
||||
else if (event->key.keyval == GDK_Return || event->key.keyval == GDK_KP_Enter)
|
||||
{
|
||||
win->_default->setFocus();
|
||||
win->_default->animateClick(type == gEvent_KeyRelease);
|
||||
return true;
|
||||
if (!control->eatReturnKey() && check_button(win->_default))
|
||||
{
|
||||
#if DEBUG_IM
|
||||
fprintf(stderr, "gcb_key_event: default button\n");
|
||||
#endif
|
||||
win->_default->setFocus();
|
||||
win->_default->animateClick(type == gEvent_KeyRelease);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,11 @@
|
|||
|
||||
//#define DEBUG_RESIZE 1
|
||||
|
||||
GList *gMainWindow::windows = NULL;
|
||||
gMainWindow *gMainWindow::_active = NULL;
|
||||
gMainWindow *gMainWindow::_current = NULL;
|
||||
|
||||
|
||||
#define CHECK_STATE(_var, _state) \
|
||||
if (event->changed_mask & _state) \
|
||||
{ \
|
||||
|
@ -332,14 +337,45 @@ static gboolean cb_expose(GtkWidget *wid, GdkEventExpose *e, gMainWindow *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
static gboolean my_key_press_event(GtkWidget *widget, GdkEventKey *event)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW(widget);
|
||||
gboolean handled = FALSE;
|
||||
|
||||
/* handle focus widget key events */
|
||||
if (!handled)
|
||||
handled = gtk_window_propagate_key_event (window, event);
|
||||
|
||||
/* Chain up, invokes binding set */
|
||||
if (!handled)
|
||||
{
|
||||
GtkWidgetClass *parent_klass = (GtkWidgetClass*)g_type_class_peek(g_type_parent(GTK_TYPE_WINDOW));
|
||||
handled = parent_klass->key_press_event(widget, event);
|
||||
}
|
||||
|
||||
/* handle mnemonics and accelerators */
|
||||
if (!handled)
|
||||
handled = gtk_window_activate_key(window, event);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
GList *gMainWindow::windows = NULL;
|
||||
gMainWindow *gMainWindow::_active = NULL;
|
||||
gMainWindow *gMainWindow::_current = NULL;
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
void gMainWindow::initialize()
|
||||
{
|
||||
// workaround GTK+ accelerator management
|
||||
|
||||
static bool _init = FALSE;
|
||||
if (!_init)
|
||||
{
|
||||
GtkWidgetClass *klass = (GtkWidgetClass*)g_type_class_peek(GTK_TYPE_WINDOW);
|
||||
klass->key_press_event = my_key_press_event;
|
||||
_init = TRUE;
|
||||
}
|
||||
|
||||
|
||||
//fprintf(stderr, "new window: %p in %p\n", this, parent());
|
||||
|
||||
stack = 0;
|
||||
|
|
|
@ -480,6 +480,7 @@ gTextArea::gTextArea(gContainer *parent) : gControl(parent)
|
|||
_use_wheel = true;
|
||||
_fix_spacing_tag = NULL;
|
||||
_has_native_popup = true;
|
||||
_eat_return_key = true;
|
||||
|
||||
onChange = 0;
|
||||
onCursor = 0;
|
||||
|
@ -572,6 +573,7 @@ void gTextArea::setReadOnly(bool vl)
|
|||
{
|
||||
gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), !vl);
|
||||
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview), !vl);
|
||||
_eat_return_key = !vl;
|
||||
}
|
||||
|
||||
GtkTextIter *gTextArea::getIterAt(int pos)
|
||||
|
|
|
@ -160,7 +160,7 @@ void gTextBox::initEntry()
|
|||
//g_signal_connect(getInputMethod(), "commit", G_CALLBACK(cb_im_commit), (gpointer)this);
|
||||
}
|
||||
|
||||
char* gTextBox::text() const
|
||||
char* gTextBox::text()
|
||||
{
|
||||
return (char*)gtk_entry_get_text(GTK_ENTRY(entry));
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ void gTextBox::insert(char *txt, int len)
|
|||
gtk_editable_insert_text(GTK_EDITABLE(entry), txt, len, &pos);
|
||||
}
|
||||
|
||||
int gTextBox::length() const
|
||||
int gTextBox::length()
|
||||
{
|
||||
const gchar *buf;
|
||||
|
||||
|
|
|
@ -33,11 +33,11 @@ public:
|
|||
//"Properties"
|
||||
int alignment() const;
|
||||
bool hasBorder() const { return _has_border; }
|
||||
virtual int length() const;
|
||||
virtual int length();
|
||||
int maxLength() const;
|
||||
bool password() const;
|
||||
int position() const;
|
||||
virtual char *text() const;
|
||||
virtual char *text();
|
||||
virtual char *placeholder() const;
|
||||
virtual bool isReadOnly() const;
|
||||
int selLength() const;
|
||||
|
|
Loading…
Reference in a new issue