Re: change keybindings



On Fri, 2006-09-08 at 10:39 +0200, Michael Wild wrote:
> hi all
> 
> as the search index for this list seems to be unavailable and google
> didn't turn up anything usefull, i'm going to ask this here (although
> probably answered many times).
> 
> how do i change the key bindings of menu items to keys without a
> modifier (i.e. withou <ctrl>, <alt> or <shift>). it works fine for any
> combination using modifier keys, but does not for "naked" keys.

GTK has issues with un-modified keys to be used as accelerators. it
doesn't interact well with the internal model that is used to
differentiate (for example) between text entry and accelerator handling.

it can be done, however, but its a little tricky. it involves catching
key press events before the default handler, knowing what type of widget
has focus, and handling keys differently depending. there is an example
in ardour (http://ardour.org/) which i have pasted below.

--p


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





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]