[comp.windows.x.motif] XmStringGetLtoR and Loss of Keyboard Focus

Uucp@resq.fidonet.org (Uucp) (03/25/91)

From  uunet!osf.org!motif-talk-request
From: uunet!alfalfa.com!nazgul (Kee Hinckley)
To:   nazgul@alfalfa.com (Kee Hinckley)
Date: Fri, 22 Mar 91 16:41:16 -0500
Cc:   larry@sunrise.com (Larry Rogers), motif-talk@osf.org

A minor correction to that code (not that it matters out of context, but...)

>     if (shell && XtParent(shell) && XtIsRealized(XtParent(shell))) {
>       XtUngrabKeyboard(XtParent(shell), CurrentTime);
>       if (shell == widget) {
>           Cardinal    numKids, i;
>           Widget      *kids;
> 
>           arglist.add(XmNchildren, &kids, XmNnumChildren, &numKids, NULL);
>           XtGetValues(shell, arglist.args, arglist.clear());
>           for (i = 0; i < numKids; ++i) if (XtIsManaged(kids[i])) break;
>           if (i < numKids) XtSetKeyboardFocus(shell, kids[i]);
>       }
        } else XtSetKeyboardFocus(shell, widget);
>     }
--  
Uucp - via FidoNet node 1:269/133
UUCP: uunet!resq!Uucp

Uucp@resq.fidonet.org (Uucp) (03/25/91)

From  uunet!osf.org!motif-talk-request
From: uunet!alfalfa.com!nazgul (Kee Hinckley)
To:   larry@sunrise.com (Larry Rogers)
Date: Fri, 22 Mar 91 16:36:18 -0500
Cc:   motif-talk@osf.org

> By the way, was it you that asked about the loss of keyboard
> focus when using accelerators to bring up dialogs?  If it was,
> I did some research.  It appears to be a timing problem that
> occurs more frequently on some systems than others.  The
> DECstation 3100 we have fails every time you do two accelerators
> in a row.  The MIPS fails only once in a blue moon.  The Sun,
> almost never.
> 
> An easy fix that I incorporated into my code was to use
> XtUngrabKeyboard directly before displaying any dialog. Note
> that I only do this if the pop-up dialog shell's parent widget is
> realized and I pass the parent widget as a parameter to the routine.
> Because the routine checks for grab conditions before doing
> an XUngrabKeyboard, it causes no X errors and because it never
> uses the widget, except to get the display/screen info, it isn't
> too picky about what widget is used.

I'm getting sick and tired of this bug.  I don't see it, incidentally on my dialogs,
but rather on a main window that I invoke and close using accelerators.  It's
clearly a focus problem, because whenever it happens I can press Alt-F to
bring up the File menu and it will bring up the File menu in the *old* window.
In fact, it will even do this if the old window is no longer mapped.  Of course
this results in an X error when it unmaps it, but fortunately I trap those.

I tried what you suggested and indeed it did seem to make things better.  (It's
hard to tell exactly, since the problem doesn't happen reliably.)  However I
now get the case where the new window comes up and doesn't visibly have the
focus anywhere, but if I start typing I find that I'm in one of the text widgets.
*However* it turns out that the translations and accelerators don't work (this
is an improvement mind you, typing didn't used to work either).

So I poked around and I looked at the change_managed code in Vendor.c and
so I added the following code to my manage routine 

    if (shell && XtParent(shell) && XtIsRealized(XtParent(shell))) {
        XtUngrabKeyboard(XtParent(shell), CurrentTime);
        if (shell == widget) {
            Cardinal    numKids, i;
            Widget      *kids;

            arglist.add(XmNchildren, &kids, XmNnumChildren, &numKids, NULL);
            XtGetValues(shell, arglist.args, arglist.clear());
            for (i = 0; i < numKids; ++i) if (XtIsManaged(kids[i])) break;
            if (i < numKids) XtSetKeyboardFocus(shell, kids[i]);
        }
    }

I do that after a realize (if it's the first time) and before I map the window.

Note the parallels here with the Dialog code we've all been talking about.
Vendor shell is doing special stuff in its change_managed routine, even though
there are other times when a VendorShell will end up on the screen without going
through that code.

So.  This code in fact seems to work pretty well.  I now get the window coming
up and it usually has a focus indicator somewhere, and the times that it doesn't,
pressing TAB will make one appear.  All the translations seem to work all the time
too.  (Mind you, I've been using this for about half an hour, but the next time I
do something it might turn out I'm all wrong and it doesn't work.)

So.  Why am I still annoyed?  Well I take this window *down* on an accelerator too.
And doing stuff at window map time isn't going to fix that.  I'm going to go off
and do a XtUngrabKeyboard when I unmap the window and see what happens there.  Maybe
that will fix it, but I really hate this kind of stuff - I'm just playing in the
dark.  Does anyone who *knows* something care to comment?

And people really think they can write a virtual toolkit that hides Motif?  Drugs!

Alfalfa Software, Inc.          |       Poste:  The EMail for Unix
nazgul@alfalfa.com              |       Send Anything... Anywhere
617/646-7703 (voice/fax)        |       info@alfalfa.com

I'm not sure which upsets me more: that people are so unwilling to accept
responsibility for their own actions, or that they are so eager to regulate
everyone else's.
--  
Uucp - via FidoNet node 1:269/133
UUCP: uunet!resq!Uucp

gabe@hpcvlx.cv.hp.com (Gabe Begeddov) (03/28/91)

/ hpcvlx:comp.windows.x.motif / Uucp@resq.fidonet.org (Uucp) /  4:56 am  Mar 25, 1991 /
   
   > An easy fix that I incorporated into my code was to use
   > XtUngrabKeyboard directly before displaying any dialog. Note
   > that I only do this if the pop-up dialog shell's parent widget is
   > realized and I pass the parent widget as a parameter to the routine.
   > Because the routine checks for grab conditions before doing
   > an XUngrabKeyboard, it causes no X errors and because it never
   > uses the widget, except to get the display/screen info, it isn't
   > too picky about what widget is used.
   
   I'm getting sick and tired of this bug.  I don't see it, incidentally on my dialogs,
   but rather on a main window that I invoke and close using accelerators.  It's
   clearly a focus problem, because whenever it happens I can press Alt-F to
   bring up the File menu and it will bring up the File menu in the *old* window.
   In fact, it will even do this if the old window is no longer mapped.  Of course
   this results in an X error when it unmaps it, but fortunately I trap those.
   
I think this problem is caused by the inability of the Xt passive grab
routines (Xt[Un]Grab[Key,Button]) to always tell when a grab has been 
released.  The Xm menu accelerators are layered on top of the Xt passive
grab facility which are in turn layered on top of the server passive grabs
(X[Un]Grab[Key,Button]).  One of the reasons the Xt wrappers were added
was to avoid event processing mishaps when toolkits/apps tried to mix
X style event redirection (via grabs  and X focus) with Xt style event
redirection (via XtSetKeyboardFocus and the modal cascade).  

Xt keeps enough state around to recoginize when a passive grab has activated
by checking incoming press events in a manner similar to the way the server
recognizes grabs.  The way that Xt recognizes that the grab has gone away
is to look at release events and if they match up with a press that has
caused a grab then it goes away.  Again, similar to the server.  Unfortunately,
this isn't good enough.  There are at least two situations where Xt
currently misses grab releases and therefore merrily continues to enforce
the grab. In your situation it would cause events to continue to be forwarded
to the hierarchy that you had unmapped.

The first is when the grab window becomes unviewable (it or one of its 
ancestors is unmapped). The server will release the grab but Xt would 
need to do some extra work in order to infer unviewabilility and thereby
know that the grab has been released.  If the window underneath the window
that was released doesn't happen to have release interest expressed on
it by this application's connection then the eventual keyrelease won't even
be seen by this client !

That is the second problem area.  While the server sees all events on all
windows :-), the client has to explicitly request events.  If the keyrelease
were to occur in a window that doesn't have release interest Xt will 
never see it and will be unable to recognize that the grab has been released.

These are both problems with the Xt implementation of passive grabs. One
way that we found to avoid this problem is to always specify the menu
accelerators and mnenomics as being activated on the release rather than
the press.  You can even argue that this is more compatable with the way
that buttons are activated, i.e. on release. You do this by explicitly 
specifying the accelerator values as "<KeyUp>MyKey".  It looks like the 
documentation (Label) says you should only use keypress events but the 
implementation actually uses KeyUp for all mnemonics and works if you use
it in your label accelerator resource spec.  I think the documentation
should be changed.

As far as the Xt bugs go, maybe a workaround, or even a real fix
will be available for R5.

Gabe

nazgul@alfalfa.com (Information Junkie) (04/01/91)

> I think this problem is caused by the inability of the Xt passive grab
> routines (Xt[Un]Grab[Key,Button]) to always tell when a grab has been 
> released.  The Xm menu accelerators are layered on top of the Xt passiv
...

> this isn't good enough.  There are at least two situations where Xt
> currently misses grab releases and therefore merrily continues to enforce
> the grab. In your situation it would cause events to continue to be forwarded
> to the hierarchy that you had unmapped.
> 
> The first is when the grab window becomes unviewable (it or one of its 
> ancestors is unmapped). The server will release the grab but Xt would 
Well that pretty much sums up the case where I'm reusing windows.  I can't
stop doing that (performance would be abysmal)
...
> That is the second problem area.  While the server sees all events on all
> windows :-), the client has to explicitly request events.  If the keyrelease
> were to occur in a window that doesn't have release interest Xt will 
> never see it and will be unable to recognize that the grab has been released.
This is probably the thing I fixed by doing an explicit unrelease everytime
I unmap a window?

> These are both problems with the Xt implementation of passive grabs. One
> way that we found to avoid this problem is to always specify the menu
> accelerators and mnenomics as being activated on the release rather than
> the press.  You can even argue that this is more compatable with the way
I've switched to doing this now.  I haven't tested it enough to see if the
problem goes away.

This still leaves one question in my mind.  This explains why the accelerators
go to the old window.  And it explains why the traversal translations don't
work (they're all defined on the down transition - not much I can do about
that).  What it doesn't explain is why the new window often comes up with
no widget showing the keyboard focus indicator.  And even with the accelerators
work, I can't tab or do anything to make the focus visible.  Where'd it go?

Alfalfa Software, Inc.          |       Poste:  The EMail for Unix
nazgul@alfalfa.com              |       Send Anything... Anywhere
617/646-7703 (voice/fax)        |       info@alfalfa.com

I'm not sure which upsets me more: that people are so unwilling to accept
responsibility for their own actions, or that they are so eager to regulate
everyone else's.