After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 362273 - menu accel keys override entry box input
menu accel keys override entry box input
Status: RESOLVED WONTFIX
Product: gtk+
Classification: Platform
Component: Class: UIManager / Actions
2.8.x
Other All
: Normal minor
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2006-10-15 03:01 UTC by David
Modified: 2014-08-30 05:04 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description David 2006-10-15 03:01:14 UTC
Either change the default behavior so that an active entry box does not lose keystrokes to a menu accelerator in the same window or improve the documentation to describe to a newbie how to fix it (eg. in the menu box documentation).

Other information:
// Here's an example program that shows my problem
// I can't enter an 'n' into the entry box.

#include <stdio.h>
#include <gtk/gtk.h>

void myAction(GtkAction *action,
             gpointer   user_data)
{
printf("Hi\n");
}

int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);

GtkWidget *window;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add (GTK_CONTAINER(window), vbox);

static GtkActionEntry entries[] = {
   { "FileMenu", NULL, "_File" },
   { "New", GTK_STOCK_NEW, "_New", "n", NULL, G_CALLBACK (myAction) },
};

static const gchar *ui_info =
   "<ui>\n"
   "  <menubar name='MenuBar'>\n"
   "    <menu action='FileMenu'>\n"
   "      <menuitem action='New'/>\n"
   "    </menu>\n"
   "  </menubar>\n"
   "</ui>";
GtkUIManager *manager;
GtkActionGroup *actions;
actions = gtk_action_group_new ("Actions");
gtk_action_group_add_actions (actions, entries, G_N_ELEMENTS (entries), NULL);
manager = gtk_ui_manager_new ();
GError *err;
err = NULL;
gtk_ui_manager_add_ui_from_string (manager, ui_info, -1, &err);
gtk_ui_manager_insert_action_group (manager, actions, 0);
gtk_window_add_accel_group (GTK_WINDOW (window),
                             gtk_ui_manager_get_accel_group (manager));
GtkWidget *mw = gtk_ui_manager_get_widget (manager, "/MenuBar");
gtk_box_pack_start (GTK_BOX (vbox),
                     mw,
                     FALSE, FALSE, 0);
GtkWidget *entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 0);
gtk_widget_show_all(window);
gtk_main();

}
Comment 1 Havoc Pennington 2006-10-15 03:09:31 UTC
I think the "n" there should be "<control>n" , no?
Comment 2 David 2006-10-15 14:49:11 UTC
No, in this example, the "n" was intended to make the accelerator key an "n", not a "<control-n>.  I guess the fact that I used this to mean "New" in this example might have been misleading, but I do want an accelerator that is a regular single key.  I'm trying to port a program written in tcl/tk that has single key accelarators to gtk+.  Down at the bottom of one window that has single key menu accelerators, I want a little entry box into which I can type a string to search for in a scrolling text box above and I want to be able to search for arbitrary text, not just text that doesn't conflict with the menu accelerator.
Comment 3 Matthias Clasen 2006-10-15 15:43:56 UTC
gtk does not work like that. menu accelerators take precedence over regular input.
So, if you use menu accelerators without modifiers, these keys are no longer available for input. 
Comment 4 David 2006-10-15 16:40:39 UTC
(In reply to comment #3)
> gtk does not work like that. 
Not until this usability request is addressed you mean. ;)

If this is a "will not fix" type of request, 
then I think the accelerator documentation should 
explicity state that it will override all other
widgets in that window.  Should I file a new documentation
request?

Comment 5 Matthias Clasen 2006-10-15 16:55:47 UTC
Changing this is certain certain to cause all kinds of problems
existing applications, so yes, this is a wontfix.
 
If you really think you need this kind of behaviour, you can install
a key snooper and bypass the normal gtk event handling if your entry
has focus. 

Feel free to move this bug to the docs .
Comment 6 David 2006-10-15 17:20:47 UTC
(In reply to comment #5)
> Changing this is certain certain to cause all kinds of problems
> existing applications, so yes, this is a wontfix.

Just to play devil's advocate for a minute, I can't believe there are many applications that have unmodified accelerators and entry boxes in the same window or they would have had the same problem that I'm having.  I can't imagine a scenario where somebody would want keystrokes to an active entry box that would otherwise display as text in the entry box stolen by the accelerator.  Can you point me to such an application?

Even if there are such applications, perhaps a solution would be to not change the default behavior, but to add a non-default mechanism to steal back printing characters from the menu accelerator to an active entry box (eg: a way to tell the menu accelerator to handle printing characters after other widgets in the window get a crack at them instead of before... like gtk_ui_manager_handle_printing_characters_last(manager)).

(I'm not trying to be difficult... just making suggestions)  
Comment 7 David 2006-10-16 18:15:52 UTC
paul@linuxaudiosystems.com provide this workaround code on the gtk mailing list.
Perhaps something similar could be incorporated into gtk as a non-default mode?

bool
key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey*
ev)
{
	GtkWindow* win = window.gobj();
	GtkWidget* focus = gtk_window_get_focus (win);
	bool special_handling_of_unmodified_accelerators = false;

	if (focus) {
		if (GTK_IS_ENTRY(focus)) {
			special_handling_of_unmodified_accelerators = true;
		}
	} 

	/* This exists to allow us to override the way GTK handles
	   key events. The normal sequence is:

	   a) event is delivered to a GtkWindow
	   b) accelerators/mnemonics are activated
	   c) if (b) didn't handle the event, propagate to
	       the focus widget and/or focus chain

	   The problem with this is that if the accelerators include
	   keys without modifiers, such as the space bar or the 
	   letter "e", then pressing the key while typing into
	   a text entry widget results in the accelerator being
	   activated, instead of the desired letter appearing
	   in the text entry.

	   There is no good way of fixing this, but this
	   represents a compromise. The idea is that 
	   key events involving modifiers (not Shift)
	   get routed into the activation pathway first, then
	   get propagated to the focus widget if necessary.
	   
	   If the key event doesn't involve modifiers,
	   we deliver to the focus widget first, thus allowing
	   it to get "normal text" without interference
	   from acceleration.

	   Of course, this can also be problematic: if there
	   is a widget with focus, then it will swallow
	   all "normal text" accelerators.
	*/


	if (!special_handling_of_unmodified_accelerators) {

		/* pretend that certain key events that GTK does not allow
		   to be used as accelerators are actually something that
		   it does allow.
		*/

		int ret = false;

		switch (ev->keyval) {
		case GDK_Up:
			ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_uparrow,
GdkModifierType(ev->state));
			break;

		case GDK_Down:
			ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_downarrow,
GdkModifierType(ev->state));
			break;

		case GDK_Right:
			ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_rightarrow,
GdkModifierType(ev->state));
			break;

		case GDK_Left:
			ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_leftarrow,
GdkModifierType(ev->state));
			break;

		default:
			break;
		}

		if (ret) {
			return true;
		}
	}
		
	if (!special_handling_of_unmodified_accelerators ||
	    ev->state & (Gdk::MOD1_MASK|
			 Gdk::MOD3_MASK|
			 Gdk::MOD4_MASK|
			 Gdk::MOD5_MASK|
			 Gdk::CONTROL_MASK)) {

		/* no special handling or modifiers in effect: accelerate first */

		if (!gtk_window_activate_key (win, ev)) {
			return gtk_window_propagate_key_event (win, ev);
		} else {
			return true;
		} 
	}
	
	/* no modifiers, propagate first */
	
	if (!gtk_window_propagate_key_event (win, ev)) {
		return gtk_window_activate_key (win, ev);
	} 


	return true;
}
Comment 8 Mike Auty 2011-05-28 19:59:30 UTC
A perfect example of this, which I just ran into with gnome-3 (bug 651344), is where I changed the new Control+Delete accelerator for "Move to wastebasket" back to just Delete.  I then found that the delete key accelerator was taking precedence when renaming a file, causing the file to be deleted, rather than the text from the filename.  Previous versions of nautilus had this key as the default, so is this a nautilus bug, or a gtk+ usability bug?
Comment 9 Matthias Clasen 2014-08-30 05:04:59 UTC
GtkAction has been deprecated