It appears that the problem stems from having a VNC viewer connected to
the display.  When I encountered the problem, I was accessing my desktop
via a VNC viewer.  This was the cause of the KeyPress/KeyRelease pairs,
and when I hold down a key on the actual keyboard connected to the
desktop without a VNC viewer connected, I am seeing the behavior that I
expect.  If a VNC viewer is connected to the display (that is, x11vnc is
running on :0), the problem also occurs even if a key is pressed on the
actual keyboard connected to the desktop.  Once the remote VNC viewer is
disconnected, the problem goes away, and it will start up again when a
remote VNC viewer is reconnected.  This latter part seems pretty odd,
but perhaps the VNC server (x11vnc) is doing something to alter the
behavior of the X server when a VNC viewer is connected.

Aaron Levinson

-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Levinson,
Aaron N
Sent: Tuesday, September 18, 2007 11:04 AM
To: [email protected]
Subject: Run-time keyboard issue encountered while porting maemo VNC
viewer toMIDs

I've been working on porting the maemo VNC viewer application (at
https://garage.maemo.org/projects/vncviewer/ ) for use on MIDs, and I've
run up against a run-time issue with the keyboard auto-repeat capability
in the X server, and I was hoping that someone on this list might be
able to further diagnose the cause of the problem.

One of the features of the VNC viewer is to scroll the main window by
holding down the hardware direction keys, a feature that also exists in
the Opera port for the Nokia Internet tablets.  For example, by holding
down the Down button, instead of sending successive down key presses to
the VNC server, it scrolls down the local VNC viewer window, thereby
scrolling the display.  This feature utilizes the following behavior:
when a hardware key is held down, the GTK Widget is signaled with repeat
key press signals until the hardware key is released, at which point the
GTK widget is signaled with a single key release signal.  The signals at
the GTK Widget layer come from the GDK layer, which has setup an X event
handler.  When the X event handler gets the KeyPress or KeyRelease
events, it translates these into the GDK_KEY_PRESS or GDK_KEY_RELEASE
GDK events, respectively, and these are later translated into the
appropriate signals by the GTKWidget class.

Unfortunately, instead of getting repeated KeyPress X events and a final
KeyRelease event, I am seeing KeyPress/KeyRelease event pairs when a
hardware key is held down.  I investigated this problem further, and it
appears to be caused by the X server, which I think is demonstrated by
an examination of the relevant GDK code.

The KeyRelease X event handler is implemented in gdkevents-xll.c as
follows:

    case KeyRelease:
      if (window_private == NULL)
        {
          return_val = FALSE;
          break;
        }

      /* Emulate detectable auto-repeat by checking to see
       * if the next event is a key press with the same
       * keycode and timestamp, and if so, ignoring the event.
       */

      if (!display_x11->have_xkb_autorepeat && XPending
(xevent->xkey.display))
        {
          XEvent next_event;

          XPeekEvent (xevent->xkey.display, &next_event);

          if (next_event.type == KeyPress &&
              next_event.xkey.keycode == xevent->xkey.keycode &&
              next_event.xkey.time == xevent->xkey.time)
            {
              return_val = FALSE;
              break;
            }
        }

      translate_key_event (display, event, xevent);
      break;

I debugged through the code (by building GTK with debugging), and it
turns out that display_x11->have_xkb_autorepeat is 1, so it never gets
into the if statement block.  display_x11->have_xkb_autorepeat is set in
gdkdisplay_x11.c, as follows:

            XkbSetDetectableAutoRepeat (display_x11->xdisplay,
                                        True,
 
&detectable_autorepeat_supported);

            GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
                                       detectable_autorepeat_supported ?
                                       "supported" : "not supported"));

            display_x11->have_xkb_autorepeat =
detectable_autorepeat_supported;

The interesting part here is the XkbSetDetectableAutoRepeat function.
The man page for XkbSetDetectableAutoRepeat states the following:

"Auto-repeat is the generation of multiple key events by a keyboard when
the user presses a key and holds it down. Keyboard hardware and
device-dependent X server software often implement auto-repeat by
generating multiple KeyPress events with no intervening KeyRelease
event. The standard behavior of the X server is to generate a KeyRelease
event for every KeyPress event. If the keyboard hardware and
device-dependent software of the X server implement auto-repeat by
generating multiple KeyPress events, the device-independent part of the
X server by default synthetically generates a KeyRelease event after
each KeyPress event. This provides predictable behavior for X clients,
but does not allow those clients to detect the fact that a key is
auto-repeating.

Xkb allows clients to request detectable auto-repeat. If a client
requests and the server supports DetectableAutorepeat, Xkb generates
KeyRelease events only when the key is physically released. If
DetectableAutorepeat is not supported or has not been requested, the
server synthesizes a KeyRelease event for each repeating KeyPress event
it generates."

So, by turning detectable auto-repeat on (which is what is happening
here), I should see the behavior that I expected, multiple KeyPress
events and a single KeyRelease event when the hardware key is released.
Plus, now the code in gdkevents-x11.c makes sense--if detectable
auto-repeat is not supported by the X server, then GDK emulates the
behavior.  However, in this case, the X server is specifically
advertising that it supports detectable auto-repeat, but it isn't
working.  Also, just for testing, I turned detectable auto-repeat off
instead of turning it on, but doing so didn't change the behavior at
all.  I even commented out the call, which should be the same as not
requesting detectable auto-repeat, but it didn't change things.

Any ideas of what could be the cause?  My experience with X servers is
pretty limited, and I'm not sure where to look next.

Thanks,
Aaron Levinson

-- 
Ubuntu-mobile mailing list
[email protected]
Modify settings or unsubscribe at:
https://lists.ubuntu.com/mailman/listinfo/ubuntu-mobile

-- 
Ubuntu-mobile mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/ubuntu-mobile

Reply via email to