<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>mntnoe.com &#187; gtk</title>
	<atom:link href="http://mntnoe.com/tag/gtk/feed/" rel="self" type="application/rss+xml" />
	<link>http://mntnoe.com</link>
	<description></description>
	<lastBuildDate>Mon, 12 Sep 2011 07:19:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Key bindings in GTK applications</title>
		<link>http://mntnoe.com/2010/02/keybindings-in-gtk-applications/</link>
		<comments>http://mntnoe.com/2010/02/keybindings-in-gtk-applications/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 23:53:57 +0000</pubDate>
		<dc:creator>Mads Navntoft Noe</dc:creator>
				<category><![CDATA[Key Bindings]]></category>
		<category><![CDATA[gtk]]></category>

		<guid isPermaLink="false">http://www.mntnoe.com/?p=80</guid>
		<description><![CDATA[Wouldn&#8217;t it be nice if you could navigate through your application&#8217;s menus using vi-like bindings? You can! Simply something like this in your ~/.gtkrc-2.0 file: binding "gtk-binding-menu" { bind "j" { "move-current" (next) } bind "k" { "move-current" (prev) } bind "h" { "move-current" (parent) } bind "l" { "move-current" (child) } } class "GtkMenuShell" [...]]]></description>
			<content:encoded><![CDATA[<p>Wouldn&#8217;t it be nice if you could navigate through your application&#8217;s menus using <em>vi</em>-like bindings? You can! Simply something like this in your<em> ~/.gtkrc-2.0</em> file:</p>
<pre>binding "gtk-binding-menu" {
    bind "j" { "move-current" (next) }
    bind "k" { "move-current" (prev) }
    bind "h" { "move-current" (parent) }
    bind "l" { "move-current" (child) }
}
class "GtkMenuShell" binding "gtk-binding-menu"</pre>
<p>Keybindings for other GTK widgets can be defined in a similar way. What about moving focus between widgets in the direction they appear?<span id="more-80"></span></p>
<pre>binding "gtk-binding-widget" {
    bind "j" { "move-focus" (up) }
    bind "k" { "move-focus" (down) }
    bind "h" { "move-focus" (left) }
    bind "l" { "move-focus" (right) }
    bind "m" { "popup-menu" () }
}
class "GtkWidget" binding "gtk-binding-widget"</pre>
<p>The <em>m</em> binding lets you pop up the context menu in any widget that not steal the modifier-less keystrokes for text input. For such widgets, prepend a modifier:</p>
<pre>    bind "&lt;mod4&gt;m" { "popup-menu" () }</pre>
<p>Likewise, the <em>move-focus</em> bindings must also be prepended with a modifier if you want to navigate through text fields.</p>
<h2>More examples</h2>
<p>Of course you can&#8217;t use modal editing for text fields, but the following makes it possible to make small corrections without moving your hands to the arrow keys:</p>
<pre>binding "gtk-binding-text" {
    bind "&lt;mod3&gt;j"         { "move-cursor" (display-lines, 1, 0) }
    bind "&lt;mod3&gt;&lt;shift&gt;j"  { "move-cursor" (display-lines, 1, 1) }
    bind "&lt;mod3&gt;k"         { "move-cursor" (display-lines, -1, 0) }
    bind "&lt;mod3&gt;&lt;shift&gt;k"  { "move-cursor" (display-lines, -1, 1) }
    bind "&lt;mod3&gt;l"         { "move-cursor" (logical-positions, 1, 0) }
    bind "&lt;mod3&gt;&lt;shift&gt;i"  { "move-cursor" (logical-positions, 1, 1) }
    bind "&lt;mod3&gt;h"         { "move-cursor" (logical-positions, -1, 0) }
    bind "&lt;mod3&gt;&lt;shift&gt;h"  { "move-cursor" (logical-positions, -1, 1) }
    bind "&lt;mod3&gt;g"         { "move-cursor" (buffer-ends, -1, 0) }
    bind "&lt;mod3&gt;&lt;shift&gt;g"  { "move-cursor" (buffer-ends, -1, 1) }
    bind "&lt;mod3&gt;y"         { "move-cursor" (buffer-ends, 1, 0) }
    bind "&lt;mod3&gt;&lt;shift&gt;y"  { "move-cursor" (buffer-ends, 1, 1) }
    bind "&lt;mod3&gt;u"         { "move-cursor" (words, 1, 0) }
    bind "&lt;mod3&gt;&lt;shift&gt;u"  { "move-cursor" (words, 1, 1) }
    bind "&lt;mod3&gt;o"         { "move-cursor" (words, -1, 0) }
    bind "&lt;mod3&gt;&lt;shift&gt;o"  { "move-cursor" (words, -1, 1) }

    # Xahlee'ish deletion
    bind "&lt;mod3&gt;d"         { "delete-from-cursor" (chars, -1) }
    bind "&lt;mod3&gt;f"         { "delete-from-cursor" (chars, 1) }
    bind "&lt;mod3&gt;e"         { "delete-from-cursor" (word-ends, -1) }
    bind "&lt;mod3&gt;r"         { "delete-from-cursor" (word-ends, 1) }
    bind "&lt;mod3&gt;s"         { "delete-from-cursor" (paragraph-ends, -1) }
    bind "&lt;mod3&gt;g"         { "delete-from-cursor" (paragraph-ends, 1) }

    # Emacs'ish deletion
    bind "&lt;alt&gt;BackSpace"  { "delete-from-cursor" (word-ends, -1) }
}
class "GtkEntry" binding "gtk-binding-text"
class "GtkTextView" binding "gtk-binding-text"</pre>
<p>This one is my favorite and works  neatly in <em>nautilus</em> if you set the default view to <em>list view</em>:</p>
<pre>binding "gtk-binding-tree-view" {
    bind "j"        { "move-cursor" (display-lines, 1) }
    bind "&lt;shift&gt;j" { "move-cursor" (display-lines, 1) }
    bind "k"        { "move-cursor" (display-lines, -1) }
    bind "&lt;shift&gt;k" { "move-cursor" (display-lines, -1) }
    bind "h"        { "move-cursor" (logical-positions, -1) }
    bind "&lt;shift&gt;h" { "move-cursor" (logical-positions, -1) }
    bind "l"        { "move-cursor" (logical-positions, 1) }
    bind "&lt;shift&gt;l" { "move-cursor" (logical-positions, 1) }
    bind "o"        { "move-cursor" (pages, 1) }
    bind "&lt;shift&gt;o" { "move-cursor" (pages, 1) }
    bind "u"        { "move-cursor" (pages, -1) }
    bind "&lt;shift&gt;u" { "move-cursor" (pages, -1) }
    bind "g"        { "move-cursor" (buffer-ends, -1) }
    bind "&lt;shift&gt;g" { "move-cursor" (buffer-ends, -1) }
    bind "y"        { "move-cursor" (buffer-ends, 1) }
    bind "&lt;shift&gt;y" { "move-cursor" (buffer-ends, 1) }
    bind "p"        { "select-cursor-parent" () }
    bind "i"        { "expand-collapse-cursor-row" (0,0,0) }
    bind "semicolon"        { "expand-collapse-cursor-row" (0,1,0) }
    bind "&lt;shift&gt;semicolon" { "expand-collapse-cursor-row" (0,1,1) }
    bind "slash"    { "start-interactive-search" () }
}
class "GtkTreeView" binding "gtk-binding-tree-view"</pre>
<p>Note that you can&#8217;t use the keys you redefine to autostart interactive search any more &#8212; you have to start it manually, in this case by using slash (/). However, I find it faster to navigate this way. Redefine the rest of the alphanummeric keys to some dummy action if you get disturbed by the interactive search when you accidently hit one of the keys not redefined.</p>
<p>You could also experiment with<em> GtkPaned</em>,  <em>GtkNotebook</em>, <em>GtkScrolledWindow</em> and <em>GtkIconView</em>:</p>
<pre>binding "gtk-binding-paned" {
    bind "&lt;mod4&gt;s" { "cycle-child-focus" (0) }
    bind "&lt;mod4&gt;&lt;shift&gt;s" { "cycle-child-focus" (1) }
}
class "GtkPaned" binding "gtk-binding-paned"</pre>
<pre>binding "gtk-binding-notebook" {
    bind "&lt;mod4&gt;d" { "change-current-page" (-1) }
    bind "&lt;mod4&gt;f" { "change-current-page" (1) }
}
class "GtkNotebook" binding "gtk-binding-notebook"</pre>
<pre>binding "gtk-binding-scrolled-window" {
    bind "&lt;mod4&gt;j" { "scroll-child" (step-down, 0) }
    bind "&lt;mod4&gt;k" { "scroll-child" (step-up, 0) }
    bind "&lt;mod4&gt;h" { "scroll-child" (step-left, 0) }
    bind "&lt;mod4&gt;l" { "scroll-child" (step-right, 0) }
    bind "&lt;mod4&gt;o" { "scroll-child" (page-down, 0) }
    bind "&lt;mod4&gt;u" { "scroll-child" (page-up, 0) }
    bind "&lt;mod4&gt;g" { "scroll-child" (start, 0) }
    bind "&lt;mod4&gt;y" { "scroll-child" (end, 0) }
}
class "GtkScrolledWindow" binding "gtk-binding-scrolled-window"</pre>
<pre>binding "gtk-binding-icon-view" {
    bind "j"        { "move-cursor" (display-lines, 1) }
    bind "&lt;shift&gt;j" { "move-cursor" (display-lines, 1) }
    bind "k"        { "move-cursor" (display-lines, -1) }
    bind "&lt;shift&gt;k" { "move-cursor" (display-lines, -1) }
    bind "h"        { "move-cursor" (logical-positions, -1) }
    bind "&lt;shift&gt;h" { "move-cursor" (logical-positions, -1) }
    bind "l"        { "move-cursor" (logical-positions, 1) }
    bind "&lt;shift&gt;l" { "move-cursor" (logical-positions, 1) }
    bind "o"        { "move-cursor" (pages, 1) }
    bind "&lt;shift&gt;o" { "move-cursor" (pages, 1) }
    bind "u"        { "move-cursor" (pages, -1) }
    bind "&lt;shift&gt;u" { "move-cursor" (pages, -1) }
    bind "g"        { "move-cursor" (buffer-ends, -1) }
    bind "&lt;shift&gt;g" { "move-cursor" (buffer-ends, -1) }
    bind "y"        { "move-cursor" (buffer-ends, 1) }
    bind "&lt;shift&gt;y" { "move-cursor" (buffer-ends, 1) }
}
class "GtkIconView" binding "gtk-binding-icon-view"</pre>
<p>Note that the bindings does not work everywhere. For instance, <em>nautilus</em> does not use <em>GtkIconView</em> for the <em>icon view</em>, nor <em>GtkNotebook</em> for tabs, so you must use the <em>list view </em>to use bindings to navigate between files, as well as use nautilus&#8217; own tab bindings  (which can be configured with <em>gtk</em>-<em>can</em>-<em>change</em>-<em>accels</em>).</p>
<h2>Further information</h2>
<p>The best place to get further information on customizing GTK application is the API. It describes the <a href="http://library.gnome.org/devel/gtk/unstable/gtk-Resource-Files.html">syntax</a> for <em>.gtkrc</em>, and the actions available for each <a href="http://library.gnome.org/devel/gtk/unstable/gtkobjects.html">widget</a>. The actions available are the signals with the label &#8220;action&#8221;. Also see <a href="http://library.gnome.org/devel/gtk/unstable/GtkSettings.html#GtkSettings.properties">GtkSettings</a> for miscellaneous settings that affects application behavior.</p>
<p>Finally it should be noted that the layout of bindings in this post serve as example only. It is not the layout that I actually use, as I have lots other bindings competing for the available key combinations <img src='http://mntnoe.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://mntnoe.com/2010/02/keybindings-in-gtk-applications/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

