Hi,

> Well, I used to like that behaviour of "typewriter capslock" (with shift
> key removing the caps lock, and the capslock affecting all keys and
> being a shift lock in fact)

Unfortunately I can't imagine how to make such mode ("affects all keys" but
"Shift cancels Caps" ) in XKB.

> I tested it and it seems to work correctly with caps:shift
> (setxkbdmap "fr" -options "caps:shift") ?

Yes, it works! And it's a big surprise to me.
Of course now I understand why it happens but I didn't guess until you wrote
about it.  :-)

Let me explain.
1) Xlib converts a keycode to a keysym in two steps.
At the first step it chooses a cell in a keyboard map table according to
the state of modifiers and gets a keysym.  And the second step is that if
Lock modifier is set Xlib tries to convert the keysym to uppercase one using
an internal table.

2) For the cell choosing it uses rules called 'key type'.  Such rule describes
what modifiers should be taken in account and what combiantion of modifiers
match each shift level. (Note that the modifers can be not Shift only but also
Control, Alt, etc.).
Each key can have own type (refer to own rule) and if there are more than one
'xkb group' in a keybaord map the key can have different types for different
groups.

3) The first step subroutine can remove some modifiers ('consume' in XKB terms)
if they are used for the sell selection.  Otherwise it would be imposible to
cancel temporary a Lock modifier action.  Thus if we want the "Shift cancels
Caps" mode we have to specify in the type description that if Shift is pressed,
Lock modifier should be removed (or hidden) and the second step will leave the
keysym unchaged.

4) xkbcomp program itself tries recognize what key is alphabetic and what key
is not and assign them different types (rules).  The algorithm is simple,
if the keysym in the first level is some lowercase letter and the keysym in
the second level is some uppercase one it is an alphabetic key (note: the
program doesn't check any matching between them).  Otherwise xkbcomp thinks
it is a 'non-alphabetic key with two levels'.
Also one can explicitly specify the key type in a keyboard map.

Now we can understand the results of your experiments.
The key [ccedilla 9] was not recognized as an alphabetic key because the second
symbol isn't an uppercase letter.
On the other hand the rule for 'simple two level' keys is:
if Shift is set choose the second level, otherwise choose the first one.
But (what I didn't guess) the rule says nothing about the consuming of Lock
modifier.  And if Lock is set the second step converts ccedilla to uppercase
Ccedilla.  If Shift is also set the first step chooses '9' and the second step
does nothing.

Actually there is not a difference between the 'two level' type and the 
'alphabetic' type in caps:internal mode except Lock+Shift case.
'Alphabetic-internal' rule chooses first level when there is not any modifiers
set and the second level when Shift is active.  If Lock (without Shift) is set
it chooses the first level keysym but allow second step to make it uppercase
one (using internal table !).
But the case Lock+Shift is processed differently.  'Two level' rule chooses
the second level symbol but 'alphabetic-internal' rule still gets the first
level keysym but consume Lock modifiers and prevents the capitalization at
the secont step.
Thus you see that the 'alphabetic-internal' rule *never* chooses the second
level if Lock is set but only pass it to or hide it from the second step.

The rule 'alphabetic' in caps:shift mode differ from both mentioned rules.
It *always* consume Lock and leave the second step idle.  On the other hand
it use Lock for choosing the second level and returns to the first level
when Shift is added to Lock.

> > > And what is exactly the difference between the caps:shift and the currently
> > > default behaviour? 
> > 
> > In "caps:shift mode" if Lock modifier is set Xlib gets from keyboard map 
> > a keysym from the second shift level the same as is chosen when Shift modifier
> > is set.
> 
> ?? You said that such behaviour is no more present.

No, I said that CapsLock key doesn't control Shift modifier (saying 'modifiers'
I don't mean keys themselvs but bit flags that the keys set).
The CapsLock key always set Lock modifier.  But in this mode Lock and Shift
modifiers (flags) cause the same action at a level choosing.
 
> > But since CapsLock key doesn't lock Shift modifier but Lock modifier
> > it allows to distinguish cases "CapsLock is active" and "CapsLock is active and
> > Shift key is pressed".  Also it allows only part of keys (alphabetical ones)
> > be affected by CapsLock.
> 
> So, it is not the second shift level that is chosen; but
> - if the second shift level is alphabetic, it is chosen;
> - if not, the first shift level is uppercased.
> 
> is that right? 

Not exactly, but it looks like that. :-)
As I tried to explain above, "if the second shift level is alphabetic" (and
uppercase) the 'alphabetic' rule is applied and in caps:shift mode
it means that the second level is chosen.  But "if not" it is a key of
'simple two level' type and it means that Lock is not taken in account at
the step (level choosing) but causes a case convertion (internal) at
the second step.

> In such case, trhe difference between caps:shift and caps:internal
> will only be visible in keyboard layouts with alphabetic letters on
> unshifted and shifted positions of a same key, but which are not different
> cases of the same letters (that is the case of the Swiss keyboard, I'll
> test with de_CH...

Yes.
 
> The case of "i" with and without dots work well; some more tests show this:
> - when i/Iabovedot are paired in a same key, Iabovedot is used as the uppercase
>   of "i". Otherwise, "I" is used as the upepercase.

Yes. If the second level keysym was not an uppercase letter the key was
recognized as non-alphabetic and 'i' was converted according to internal table.

> - when "idotless" is paired with "I", then "I" is used as the uppercase;
>   otherwise CapsLock has no effect on that letter and the lowercase
>   "idotless" is returned. 

Probably ConvertCase procedure doesn't know how to convert it to uppercase.

> In fact the behaviour (with caps:internal or caps:shift, I see no difference
> at all) seems to be this one (when capslock is active):
> 
> - if position shift 1 is a lowercase letter, and if shift2 is an uppercase
>   letter; then the symbol in position shift2 is used as the uppercase value,
>   and the symbol in shift1 as the lowercase value.
>   that is, pressing the key gives the uppercase. pressing shift-key gives
>   the lowercase (the letters may be different, eg: [ x, A ] will
>   work.

Right.  As I said xkbcomp just wants the first symbol be lowercase and the
second one be uppercase to consider the key as alphabetic.

> - otherwise, for each alphabetic letter, the uppercase letter is returned;
>   also for symbols in shift2 (eg: [ x, a ] gives "X" when you press
>   the key, and "A" when pressed with shift).

It's understandable too. Suck keys are processed as 'two level non-alphabetic'
it means that Shift chooses the level and Lock causes a case-convertion at
the second step.  Since the 'alphabetic' rule isn't used there it doesn't
matter what mode it has.  Anyway the 'internal case-conversion' happens.

> - for non alphabetic letters, the symbol is returned as (CapsLock has
>   no effect)

Yes. The rule in this case is 'two level'.  Shift modifier chooses level.
Lock does nothing.

> So it seems the problem is indeed solved; but the behaviour (a quite good
> one in fact) is different of what you and I thought it was.

Yes. Thank you for your experiments.

I wrote a test program that prints keysyms for all keys in a map for all
combinations of Lock and Shift.  And than I ran it for all layouts in both
modes and compared the results.
There are few differences (in 'tr' for example) and in all cases caps:shift
produces more reasonable result.

There is one only exeption in 'ca' and 'ca_enhanced' maps:
the key  [ eth,    Dstroke ].  It's recognized as alphabetical one
(lowercase - uppercase letters) and the results are different.
Lock with caps:internal gives ETH
but with caps:shift it gives Dstroke (and there is not way to get ETH).
But it can be fixed easy in the map.  We just have to specify explicitly that
the key must be 'two level' but not 'alphabetic'.

Also there is a problem with new 'one group' keymaps that appeared in 4.3.0.
In such keymap there are many four-level keys.  The problem is that
third and fourth levels in some cases is an alphabetic pair but in some other
is not, therefore they should be processed differently for different kinds of
four-level keys.  But I made only one 'alphabetic' rule for all such keys and
too simplified procedure for recognizing them as alphabetic (it checks
only two first levels and ignores others).
Now I see that I have to improve such keys processing.  But when it be done
I think we can make caps:shift mode the default.

-- 
 Ivan U. Pascal         |   e-mail: [EMAIL PROTECTED]
   Administrator of     |   Tomsk State University
     University Network |       Tomsk, Russia
_______________________________________________
Devel mailing list
[EMAIL PROTECTED]
http://XFree86.Org/mailman/listinfo/devel

Reply via email to