bind . <Control-k> { puts k }
Then "k" is printed when I press Control-k. Not Shift-Control-k, not
Alt-Control-k, but only and exclusively Control-k.
When I bind:
bind . <k> { puts k }
Then "k" is printed when I press k, Control-k, Alt-k, also any other key
together with k (but not shift - probably I should use <K> not <k> for
shift:).
How to specify binding so that the event is raised only and exclusively when I
press k without any other key together?
I tried this on Tkcon on Windows, with ActiveTcl.
--
// _ ___ Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl>
\\ L_ |/ `| /^\ ,() <ethourhs(O)gmail.com>
// \_ |\ \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx
"I am allergic to Java because programming in Java reminds me casting spells"
Bind to <KeyPress-k> as before, but add additional bindings for
<Control-k>, <Alt-k>, etc. that do nothing, but which are not empty
strings (empty string would remove a non-existent binding). These soak
up modified keypresses through being more specific than the basic
binding to <KeyPress-k>, giving you the effect you're after.
When I do this, I usually use a comment for the binding so that it is
clear what is going on when I review the code.
Donal.
proc bind'plainkey {tag key script} {
bind $tag <Control-$key> { }
bind $tag <Alt-$key> { }
bind $tag $key $script
}
% bind'plainkey all x {puts Hello}
You forgot <Meta-$key>.
You seem also to forget <Meta1-$key> ... <Meta6-$key>, <Button1-$key>
... <Button5-$key>, <Lock-$key> etc.
I'm developing initial "scratches" for a GUI library for C++ and the Tk event
system looked like a very worthwhile basis. The <Mod-Mod...-Type-Detail> event
structure looks very fine, especially for event filtering.
However binding <k> to response for <k>, <Control-k>, <Alt-K> and other
modifiers but Shift, is not a good idea for me. I think if a user wants to
bind a key for both <k> and <Control-k>, they can make separate bindings.
I would provide something like:
bind_event( w, Key<'k'>, response_for_key );
bind_event( w, Control-Key<'w'>, close_window, ea_widget );
bind_event( w, Plain-Key<'w'>, show_w_letter );
But I don't think users want to bind handlers to an event triggered by "some
key with any modifier".
> You seem also to forget <Meta1-$key> ... <Meta6-$key>, <Button1-$key>
>... <Button5-$key>, <Lock-$key> etc.
I just looked at my keyboard, and Ctrl and Alt (AltGr too, not sure
whether Tk handles that) is what I have :^) But it should be evident to
tailor the code to other needs.
>
> You forgot <Meta-$key>.
>
> You seem also to forget <Meta1-$key> ... <Meta6-$key>, <Button1-$key>
> ... <Button5-$key>, <Lock-$key> etc.
>
> I'm developing initial "scratches" for a GUI library for C++ and the Tk event
> system looked like a very worthwhile basis. The <Mod-Mod...-Type-Detail> event
> structure looks very fine, especially for event filtering.
>
> However binding <k> to response for <k>, <Control-k>, <Alt-K> and other
> modifiers but Shift, is not a good idea for me. I think if a user wants to
> bind a key for both <k> and <Control-k>, they can make separate bindings.
>
In all my years of UI design and development I don't think this has once
been an issue, where I wanted <k> to do something but <control-k> do
nothing. It makes sense that if you have no other purpose for alt-k,
meta-k, command-k, opt-k, meta2-k, control-meta-k,
control-meta-opt-command-k etc, there's absolutely no harm, and maybe a
little good, in that they act as if the modifier wasn't pressed.
So, to me, tk's design once again proves to have been arrived at with
remarkable foresight. The default behavior is at worst harmless, at best
convenient, and yet flexible enough to achive whatever result you need.
Of course, in all my years of UI design and development I have only seen
and done a small subset of all possible designs so my opinions are
biased towards my own personal experience. Still, I think tk gets it
right in this regard.
--
Bryan Oakley
http://www.tclscripting.com
> Sektor van Skijlen wrote:
> > How to specify binding so that the event is raised only and exclusively when I
> > press k without any other key together?
>
> Bind to <KeyPress-k> as before, but add additional bindings for
> <Control-k>, <Alt-k>, etc. that do nothing
As people point out, the list gets pretty long.
Another solution (also not without problems) is to test the
modifier state within the binding:
bind . <Key-k> {if {%s==0} { your binding here }}
Watch out for confusion if you bind to capital letters or other shifted
characters.
--
Donald Arseneau as...@triumf.ca
> When I bind:
>
> bind . <k> { puts k }
>
> Then "k" is printed when I press k, Control-k, Alt-k, also any other key
> together with k (but not shift - probably I should use <K> not <k> for
> shift:).
Yes. Similar for caps-lock activated. This irregularity is convenient
for most purposes, but is a devil if you are doing complex multi-modifier
bindings!
> How to specify binding so that the event is raised only and exclusively when I
> press k without any other key together?
For now, see other answers.
I would really like to see such a facility built into Tk! I don't like
the "Nomodifier" name, but another like "Plain" would be good. I envision
it working with the same exception for Shift, so that <Plain-K> would
actually fire (despite the shift being pressed).
Unfortunately, I have no illusions about being able to provide a patch
for a Plain- modifier.
What happened to the Any- modifier? I seem to remember it, but don't see
any evidence beyond the fact that Tk accepts it. I suppose it is undocumented
because it is implicit on any binding. Does it mean that at some point
the *intent* was to have [bind . <k> { puts k }] work for unmodified k
only, and <Any-k> would have the current meaning of <k>?
I wouldn't mind a real Any- modifier that encompassed the Shift- modifier,
so <Any-k> would fire for K (Shift-k).
--
Donald Arseneau as...@triumf.ca
> > When I bind:
> >
> > bind . <k> { puts k }
> >
> > Then "k" is printed when I press k, Control-k, Alt-k, also any other key
> > together with k (but not shift - probably I should use <K> not <k> for
> > shift:).
> Yes. Similar for caps-lock activated. This irregularity is convenient
> for most purposes, but is a devil if you are doing complex multi-modifier
> bindings!
> > How to specify binding so that the event is raised only and exclusively when I
> > press k without any other key together?
> For now, see other answers.
Yes, that was another solution that did not come to my mind (while 'twas so
simple :).
> I would really like to see such a facility built into Tk! I don't like
> the "Nomodifier" name, but another like "Plain" would be good. I envision
> it working with the same exception for Shift, so that <Plain-K> would
> actually fire (despite the shift being pressed).
> Unfortunately, I have no illusions about being able to provide a patch
> for a Plain- modifier.
> What happened to the Any- modifier? I seem to remember it, but don't see
> any evidence beyond the fact that Tk accepts it. I suppose it is undocumented
> because it is implicit on any binding. Does it mean that at some point
> the *intent* was to have [bind . <k> { puts k }] work for unmodified k
> only, and <Any-k> would have the current meaning of <k>?
> I wouldn't mind a real Any- modifier that encompassed the Shift- modifier,
> so <Any-k> would fire for K (Shift-k).
Of course discussing about that seems to be an academic discussion - possibly
none of GUI programmers see this a problem.
I'm asking about that because I am creating a similar event system and I try
to reconsider, how much it is worth to base on Tk.
This problem, I think, should be solved the following way:
- a key event is triggered with a single key without modifier: Key<'k'>
- a key with modifier can be: Control-Key<'k'>, Shift-Key<'k'>
- Shifted keys are the same as that key with shift. That is:
- Key<'K'> is the same as Shift-Key<'k'>
- Key<'K'> is the same as Shift-Key<'K'> (Shift is redundant)
- if a user wants to trigger his event at, say, both k and Ctrl-k,
they have to use separate bindings:
bind_event( w, Key<'k'>, klose_window, ea_widget );
bind_event( w, Control-Key<'k'>, klose_window, ea_widget );
I don't think users want applications in which 'k' does the same as Ctrl-k.
While with letters this is trivial, how would it
do with e.g. <Shift-comma> ? (on US-keyboards this
would be "<", on german ones, its ";")
As long as your framework doesn't assume a certain
keyboard-layout, and as long as the application doesn't
depend on any two differently "modified" keys being really
distinct (";" and Shift-","), this shouldn't be a problem.
PS: for the double-click timings: most people won't ever
touch them, but people with certain disabilities might
very strongly depend on being able to enlarge this time.
Actually, it does nothing. It's there for compatability with Tk 3, and
probably ought to be removed sometime. It's useless.
Donal.
> While with letters this is trivial, how would it
> do with e.g. <Shift-comma> ? (on US-keyboards this
> would be "<", on german ones, its ";")
Huh! Didn't think about it. It seems to be a little problem.
For example, I would state that Shift-Key<';'> is the same as Key<':'>. Which
need not be true, alas.
I think the only reasonable way is to state the shift-defaults for letters
only, but simultaneously also disable Shift modifier for non-letters. I try
to think also that there should be no "Shift" at all :).
> As long as your framework doesn't assume a certain
> keyboard-layout, and as long as the application doesn't
> depend on any two differently "modified" keys being really
> distinct (";" and Shift-","), this shouldn't be a problem.
This still will depend on implementation. If, for example, the underlying
window system will be able to help me with associating Shift-, with ; in case
of German layout (i.e., when the key ';' is coming, I am able to recognize it
as Shift-, also, or - more reasonably - binding to Shift-Key<','> will map to
';' on German layout and to '<' on English layout).
How does Tk deal with this problem?
> PS: for the double-click timings: most people won't ever
> touch them, but people with certain disabilities might
> very strongly depend on being able to enlarge this time.
Yes. So I think some association with window-system-specific setting is
reasonable.
Remember that in bind <;>, the ";" refers to the symbol, not the particular
key. So with the German keyboard <Shift-,> cannot occur because you cannot
enter a comma with the shift key depressed. <Shift-;> is redundant since
you must use the shift key for ";". <Shift-A> will occur when "a" is
hit with the shift key depressed -- it will not occur as the result of
hitting "a" in shift-lock state.
This stuff can get *very* complicated.
In the X world, an application might be talking to more than one display,
so you have the possibility of one display using an English kb with another
using a German one.
In a variation of this, some keyboards use "Alt-Gr" to allow a shift between,
say, English and Russian character sets -- you really have two keyboard
layouts on a single keyboard.
Then there are the Asian languages which typically use an "input method",
which is a separate program -- often of considerable complexity -- to
pre-filter the keystrokes to compose wide characters or UTF-8.
I believe Tk handles all of the above -- the situation is so complicated
that it is even difficult to even state what Tk handles. Mostly it
depends on the underlying windowing system to translate the keycode to
a keysym.
The previous posts on this thread seem to indicate one thing that is
lacking in Tk. It seems that you lack the ability to say, for example,
use exactly the modifier list given (so <a> does not include <Alt-a>).
The Xt scheme, on which Tk is based, addresses this as follows:
<a> any modifiers (exactly as in Tk)
<None-a> no modifiers (not easily done in Tk)
<!Alt-Shift-A> exactly Alt and Shift (not easy in Tk)
<:Alt-Shift-A> Alt and Shift, don't care about any others (like Tk)
and using the above rules this gives
<!-a> like <None-a>
<:Alt-a> require Alt, don't care about Shift, Ctrl, etc
I'll let you decide if this is useful :)
> In the X world, an application might be talking to more than one display,
> so you have the possibility of one display using an English kb with another
> using a German one.
Complications, I think, come up when you try to translate the keys someone
in hitting on the keyboard, to symbols that describe the action.
I try to get easy always thinking that if people spelled up libraries, which
work and are used, then good solutions have been already refined inside them.
> I believe Tk handles all of the above -- the situation is so complicated
> that it is even difficult to even state what Tk handles. Mostly it
> depends on the underlying windowing system to translate the keycode to
> a keysym.
Yes, of course, and the complications connected to this translation can be
left for the implementation.
I just try to decide, what should the library do, when a user wants to bind a
handler to such an event: Shift-Key<','>:
- bind event to <
- bind event to a symbol, which is assigned to <Shift-,> on current layout
- cause a compile error
I am strongly for the third solution.
> The previous posts on this thread seem to indicate one thing that is
> lacking in Tk. It seems that you lack the ability to say, for example,
> use exactly the modifier list given (so <a> does not include <Alt-a>).
> The Xt scheme, on which Tk is based, addresses this as follows:
> <a> any modifiers (exactly as in Tk)
> <None-a> no modifiers (not easily done in Tk)
> <!Alt-Shift-A> exactly Alt and Shift (not easy in Tk)
> <:Alt-Shift-A> Alt and Shift, don't care about any others (like Tk)
> and using the above rules this gives
> <!-a> like <None-a>
> <:Alt-a> require Alt, don't care about Shift, Ctrl, etc
> I'll let you decide if this is useful :)
Hmm... I have always thought that there is no value in binding to, say, 'a'
with any modifier, so that, for example, binding to 'a' causes that this
handler be called for 'a', Ctrl-a, Alt-a etc.
I think it should allow user to bind, for example to:
- Shift-Control-6, which will trigger, when a user presses Shift-Ctrl-6,
regardless of what symbol is assigned to Shift-6 on current layout.
- Control-^, which will trigger, when a user presses Control with a whatever
key combination is assigned to '^' symbol on current layout
This way, the library must contain symbols for Shift-6 and '^' as separate
symbols and assign them to '^', if the keyboard layout says so. But I don't
know, what would happen, if a user changed the keyboard layout, while the
application is still running. Seems like the key symbol translation must be
done dynamically and it also must be strongly dependent on the implementation.
I have exaggerated ambitions. I'd like that this library interface be able to
implement with whatever you want: not only native window systems (Windows, X,
Mac), but also ncurses and Ajax (see: Wt).
Looxlike Tk does not bind (not: does not allow) the Shift-Key-6 combination to
be triggered from '^'.
It binds it, but the OS does not generate it. Instead, the OS really
generates <Shift-KeyPress-asciicircum> in that situation, and Tk does
not know that they happen to be the same physical key. The OS knows, but
it doesn't tell, and if you're using input methods of some sort (the
simplest of which is a Compose key) a shifted '6' might not be delivered
to Tk at all.
Donal.
No shift key? Yowch! That'd massively increase the number of keys
needed. I want a keyboard, not a full cathedral organ-loft...
Donal.
:)))
There are several reasons, why the Shift key should remain. We want, for
example, to bind a key Shift-Space for something. The internal symbol may be
different and the Shift flag may be not present in flags at all - just another
numeric symbol.
On the other hand, you don't need explicit Shift key, when you try to bind
keys, which have different keysyms for shifted and not shifted keys. They
include letters and graphical symbols. But keys like Space, F1, Delete etc.
still have Shift as an alternative.