Oops. Sorry, I didn't know that "tab" was "send" in this gmail's keyboard shortcuts. Resend, more complete at bottom.<br><br><div class="gmail_quote">---------- Forwarded message ----------<br>From: <b class="gmail_sendername">Jameson Quinn</b> <span dir="ltr"><<a href="mailto:jameson.quinn@gmail.com">jameson.quinn@gmail.com</a>></span><br>
Date: 2009/4/30<br>Subject: Keyboard shortcuts<br>To: sugar-devel <<a href="mailto:sugar-devel@lists.sugarlabs.org">sugar-devel@lists.sugarlabs.org</a>><br><br><br>I am interested in making our keyboard shortcuts discoverable, ubiquitous, and consistent. This is especially important because of the approximately half a million demon-possessed trackpads that OLPC has shipped (not blaming; I thought that the resistive pad was a cool idea too, in fact, it's still a cool idea and the XO had a pretty good batting average with its attempted miracles).<br>
<br>The overall plan is outlined at <a href="http://wiki.sugarlabs.org/go/Design_Team/Vision/Proposals/Keyboard_Action" target="_blank">http://wiki.sugarlabs.org/go/Design_Team/Vision/Proposals/Keyboard_Action</a> . I've posted it here before, but since I combined it with another idea about the home view, it didn't get discussed much. I'm starting to code it, so I want to get some more consensus before I go too far. I'll start with vision, then talk about implementation.<br>
<br>The vision is to provide software support for three desirable qualities.<br><br><b>Discoverable</b>. Without discoverability, shortcuts are useless. And we have pre-literate kids as a part of our user base, so including "ctrl-x" in our popdowns isn't going to cut it. My basic idea is that when the user presses/holds ctrl, the shortcuts show up as translucent letters in front of the toolbar buttons. Some open questions:<br>
<br>Delay? My instinct is yes, so that fast typers aren't slowed down by UI candy, but a pretty small one - around 300-700 ms. I'd rather not make this configurable.<br><br>Non-"ctrl" shortcuts: My idea is to have two lines: the top third of the toolbar button can say "Alt" or "Shift", then the bottom two thirds has the letter. F5 or Pause or whatever should just say the key name. The problem is, how do you distinguish ctrl-alt-a from alt-a, and ctrl-F5 from F5. IMO it's not actually a tragedy if you just don't make that distinction.<br>
<br><b>Ubiquitous. </b>To me, this goal means increasing our software support for the developer/translator team assigning shortcuts. It's true, it's really just one line and one string per button (<span style="font-family: courier new,monospace;">customButton.props.accelerator = _('<ctrl>b')</span>) but that's a big nuisance for translators, and programmers are meant to be lazy. So I think you should be able to assign the accelerator from within the translatable string. GTK already has a similar mechanism, but it's inappropriate. Setting the label to "go _next" will, if the use_underline property is true, set the mnemonic, a kind of shortcut that works only if the control's visible, to alt-n, and draw the label with the n underlined. Four problems: we care about tooltip, not label; we want the shortcut to be available when you're on a different toolbar; we want ctrl, not alt; and this doesn't seem to work in sugar, for reasons I've not investigated. So I propose doing the same thing, but using the tooltip, a real shortcut, ctrl, and the character u"\u00ad" which is "soft hyphen", ie, by nature an invisible typesetting mark. Issues: I haven't tested if you can use the backslash escape to get this in Pootle, if not it's a problem.<br>
<br><b>Consistent</b>. This means dealing with all the shortcuts in a unified fashion. First principle is, ctrl for activity shortcuts, alt for global/frame ones, ctrl-alt for modified ctrl shortcuts (ie, ctrl-alt-v is paste-and-pop-clipboard), ctrl-shift or alt-shift is backwards (redo or alt-shift-tab). Here's my list of global shortcuts/key assignments, copied from keyhandler.py with my proposed changes in bold, please add anything I've forgotten:<br>
<span style="font-family: courier new,monospace;">_actions_table = {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> 'F1' : 'zoom_mesh',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> 'F2' : 'zoom_group',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> 'F3' : 'zoom_home',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> 'F4' : 'zoom_activity',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> 'F9' : 'brightness_down',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> 'F10' : 'brightness_up',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> '<alt>F9' : 'brightness_min',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> '<alt>F10' : 'brightness_max',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> 'XF86AudioMute' : 'volume_mute',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> 'F11' : 'volume_down',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> 'XF86AudioLowerVolume' : 'volume_down',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> 'F12' : 'volume_up',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> 'XF86AudioRaiseVolume' : 'volume_up',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> '<alt>F11' : 'volume_min',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> '<alt>F12' : 'volume_max',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> '0x93' : 'frame',</span><br style="font-family: courier new,monospace;"><b><span style="font-family: courier new,monospace;"> 'Insert' : 'frame', #for SoaS<br>
'0x00' : 'frame', #for SoaS on Xephyr, see below.</span></b><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> '0xEB' : 'rotate',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> '<alt>Tab' : 'next_window',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> '<alt><shift>Tab' : 'previous_window',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> '<alt>Escape' : 'close_window',</span><br style="font-family: courier new,monospace;">
<b><span style="font-family: courier new,monospace;"> '<alt><ctrl>Escape' : 'close_window_discard_from_journal',</span></b><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> '0xDC' : 'open_search',<br><b> '<alt>1' : </b></span><b><span style="font-family: courier new,monospace;">'zoom_mesh'</span><span style="font-family: courier new,monospace;">,<br>
#... alt-numeral should be like the top row of the frame, so alt-5 would be journal <br> #and alt-6 first running activity <br> '<alt>Enter' : 'hide-toolbar', #if implemented by activity<br>
'<alt>v' : 'view-source',<br> '<alt>c' : 'screen-capture',<br> 'PrtSc' : 'screen-capture',</span></b><br> <br style="font-family: courier new,monospace;">
<b><span style="font-family: courier new,monospace;"> '<alt>s' : 'say_text',</span></b> #was alt-shift-s<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"># the following are intended for emulator users</span><br style="font-family: courier new,monospace;">
<b><span style="font-family: courier new,monospace;"># '<alt><shift>f' : 'frame',</span> #removed</b><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> '<alt><shift>q' : 'quit_emulator',</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> 'XF86Search' : 'open_search',</span><br style="font-family: courier new,monospace;"><b><span style="font-family: courier new,monospace;"># '<alt><shift>o' : 'open_search', #removed</span></b><br style="font-family: courier new,monospace;">
<b><span style="font-family: courier new,monospace;"># '<alt><shift>r' : 'rotate', #removed</span></b><br>
<br>...<br>Also, ctrl-numeral would choose toolbars, and toolbar tabs would get little translucent numbers when you held control.<br><br>Implementation<br><br>Basically, I propose to do all this magic only on the subclasses already existing in sugar-graphics. Some of this is more-or-less a monkeypatch to GTK itself, but I am not signing up for dealing with upstream, and in fact much of this is not even appropriate for upstream. Some of you might feel that the "ubiquitous" stuff (saving LOC and strings) is not worth the maintenance headache to do it in such a hack-y fashion. If enough people say so, I have no problem abandoning that part of the plan.<br>
<br>OK, sorry for the double-post, and none of this is set in stone. I'm happy to discuss and bikeshed a bit, but I have already started coding, so please comment relatively quickly if you object to the whole idea.<br>
<br>Jameson<br>
</div><br>