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:
gambas 2020-11-24 21:37:55 +01:00
parent 38eefd7d21
commit 9c3fc87265
10 changed files with 96 additions and 37 deletions

View file

@ -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:

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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();

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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;