You are not logged in.

#1 2014-02-18 23:13:41

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

[SOLVED] GtkWindow blocks keyboard shortcuts for widgets

Hey all,

I'm writing a small GTK editor, mostly for the fun and learning. I've been working on it for a few hours now and I hit a bump I can't seem to find a solution for. Basically, I have a GtkWindow, with a GtkNotebook inside it. This notebook has tabs, a tab has a GtkScrolledWindow and that houses a GtkSourceView widget which displays the files that are currently being edited.

I don't want to clutter the UI with buttons and toolbars so I opted for keyboard shortcuts, however there is a problem here: the GtkWindow, which listens for key presses on the key-press-event, blocks keyboard shortcuts that are natively in GtkSourceView. I have been trying to find a solution to this, so that I start from GtkSourveView to look up if a matching shortcut has been found and if not, work my way up up the chain I described above, but so far I have been unsuccesful. I did find this piece of code from Gedit which seems to be what I want but I get stuck on the g_type_class_peek_parent part.

Can somebody give me a nudge in the right direction?

Thanks!

Last edited by Unia (2014-02-19 14:43:10)


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#2 2014-02-19 13:16:44

jjacky
Member
Registered: 2011-11-09
Posts: 347
Website

Re: [SOLVED] GtkWindow blocks keyboard shortcuts for widgets

If I understand you right, you just need to connect to key-press-event and do pretty much what GEdit does, process the event in the order you want. Because they extend GtkWindow they use g_type_class_peek_parent to chain up directly to GtkWindow's parent class, skipping GtkWindow's implementation since they already did what it would do (only in a different order).

If you don't do that (extend GtkWindow) and simply connect to the signal, you can process it in the order you want (since it's RUN_LAST your handler comes before the class closure), and then simply return FALSE if it hasn't been handled yet. It means it'll go through the same things again (but in "original" order), and then it'll chain up properly.

Although G_TYPE_INSTANCE_GET_CLASS() is only meant to be used in implementations, I guess you could also use it to get GtkWindowClass, then use g_type_class_peek_parent() to get the parent class and chain up directly as well.

(Side note, I'm not sure GEdit actually skips calling GtkWindow's implementation as the comment says, since it looks like they're calling the implementation on their grand parent's class, which is... GtkWindow! Since they actually extend GtkApplicationWindow, which extends GtkWindow. It doesn't hurt since, as it would with the signal, it just means the event goes through the same things in different order before being chained up properly, but that might still be a "bug" I guess. I could also be wrong of course...)

Hope this helps.
-j

Offline

#3 2014-02-19 13:59:03

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] GtkWindow blocks keyboard shortcuts for widgets

Wow, that was easier than I thought! I do not extend GtkWindow myself (I don't know how to, nor do I see why I would need this as I try to keep it simple).

Just to be sure what I have now is right, here is what I currently have. The on_keypress_window function gets called whenever there is a key-press-event and it delegates this event in the order I described in the OP. Then, I have added a key-press-event to the GtkSourceView object which calls on_keypress_view. Is this the correct way to go about it?

static gboolean
on_keypress_window(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);

	/* handle mnemonics and accelerators */
	if(!handled)
		handled = gtk_window_activate_key(window, event);

	/* we went up all the way, these bindings are set on the window */
	if((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK ) {
		switch(event->keyval) {
			case GDK_KEY_o: open_file(); return TRUE; break;
			case GDK_KEY_n: /*new_file();*/ return TRUE; break;
			case GDK_KEY_w: /*close_tab();*/ return TRUE; break;
			case GDK_KEY_s: /*save_file();*/ return TRUE; break;
			case GDK_KEY_r: /*reload_file();*/ return TRUE; break;
		}
	}

	return TRUE;
}

....

static gboolean
on_keypress_view(GtkWidget *widget, GdkEventKey *event) {
	if((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK ) {
		switch(event->keyval) {
			/*I still have to implement these*/
			default: return FALSE; break;
		}
	}

	return FALSE;
}

Last edited by Unia (2014-02-19 14:00:01)


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#4 2014-02-19 14:26:56

jjacky
Member
Registered: 2011-11-09
Posts: 347
Website

Re: [SOLVED] GtkWindow blocks keyboard shortcuts for widgets

Looks right, yes. Except I'm not sure you meant to return TRUE by default in on_keypress_window ? If you do it won't get processed further, but if you've not handled it yourself you should return FALSE to let GtkWindow process it. You probably want to return handled instead; and maybe your handling of keys should also only be done if handled is still FALSE. E.g:

static gboolean
on_keypress_window(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);

	/* handle mnemonics and accelerators */
	if(!handled)
		handled = gtk_window_activate_key(window, event);

	/* we went up all the way, these bindings are set on the window */
	if(!handled && (event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK ) {
		switch(event->keyval) {
			case GDK_KEY_o: open_file(); return TRUE; break;
			case GDK_KEY_n: /*new_file();*/ return TRUE; break;
			case GDK_KEY_w: /*close_tab();*/ return TRUE; break;
			case GDK_KEY_s: /*save_file();*/ return TRUE; break;
			case GDK_KEY_r: /*reload_file();*/ return TRUE; break;
		}
	}

	return handled;
}

Offline

#5 2014-02-19 14:43:00

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] GtkWindow blocks keyboard shortcuts for widgets

Thanks for your help!


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

Board footer

Powered by FluxBB