Re-enabled Xnest fix for focus in + modifier bug.

* See https://bugs.freedesktop.org/show_bug.cgi?id=3030

Signed-off-by: Xiaoyang Yu (Max) <max.a.yu@intel.com>
Reviewed-by: Mikhail Gusarov <dottedmag@dottedmag.net>

This takes the xnest way of working around this (see
5904ef2ccd "xnest: restore
xnestUpdateModifierState") and copies it to Xephyr.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Xiaoyang Yu (Max) 2010-06-04 17:17:53 +08:00 committed by Peter Hutterer
parent 505724c5f3
commit db0d3d4e57

View File

@ -38,6 +38,8 @@
#include "ephyrglxext.h" #include "ephyrglxext.h"
#endif /* XF86DRI */ #endif /* XF86DRI */
#include "xkbsrv.h"
extern int KdTsPhyScreen; extern int KdTsPhyScreen;
#ifdef GLXEXT #ifdef GLXEXT
extern Bool noGlxVisualInit; extern Bool noGlxVisualInit;
@ -748,75 +750,55 @@ ephyrScreenFini (KdScreenInfo *screen)
void void
ephyrUpdateModifierState(unsigned int state) ephyrUpdateModifierState(unsigned int state)
{ {
#if 0
DeviceIntPtr pkeydev;
KeyClassPtr keyc;
int i;
CARD8 mask;
pkeydev = inputInfo.keyboard; DeviceIntPtr pDev = inputInfo.keyboard;
KeyClassPtr keyc = pDev->key;
if (!pkeydev) int i;
return; CARD8 mask;
int xkb_state;
/* This is pretty broken. if (!pDev)
* return;
* What should happen is that focus out should do as a VT switch does in
* traditional servers: fake releases for all keys (and buttons too, come
* to think of it) currently down. Then, on focus in, get the state from
* the host, and fake keypresses for everything currently down.
*
* So I'm leaving this broken for a little while. Sorry, folks.
*
* -daniels
*/
keyc = pkeydev->key; xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state);
state = state & 0xff; state = state & 0xff;
if (keyc->state == state) if (xkb_state == state)
return; return;
for (i = 0, mask = 1; i < 8; i++, mask <<= 1)
{
int key;
/* Modifier is down, but shouldn't be */ for (i = 0, mask = 1; i < 8; i++, mask <<= 1) {
if ((keyc->state & mask) && !(state & mask)) int key;
{
int count = keyc->modifierKeyCount[i]; /* Modifier is down, but shouldn't be
*/
for (key = 0; key < MAP_LENGTH; key++) if ((xkb_state & mask) && !(state & mask)) {
if (keyc->xkbInfo->desc->map->modmap[key] & mask) int count = keyc->modifierKeyCount[i];
{
int bit; for (key = 0; key < MAP_LENGTH; key++)
BYTE *kptr; if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
int bit;
kptr = &keyc->down[key >> 3]; BYTE *kptr;
bit = 1 << (key & 7);
kptr = &keyc->down[key >> 3];
if (*kptr & bit && ephyrKbd && bit = 1 << (key & 7);
((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled)
KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE); /* release */ if (*kptr & bit)
KdEnqueueKeyboardEvent (ephyrKbd, key, TRUE);
if (--count == 0)
break; if (--count == 0)
} break;
} }
/* Modifier shoud be down, but isn't */
if (!(keyc->state & mask) && (state & mask))
for (key = 0; key < MAP_LENGTH; key++)
if (keyc->xkbInfo->desc->map->modmap[key] & mask)
{
if (keyc->xkbInfo->desc->map->modmap[key] & mask && ephyrKbd &&
((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled)
KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE); /* press */
break;
}
} }
#endif
/* Modifier shoud be down, but isn't
*/
if (!(xkb_state & mask) && (state & mask))
for (key = 0; key < MAP_LENGTH; key++)
if (keyc->xkbInfo->desc->map->modmap[key] & mask) {
KdEnqueueKeyboardEvent (ephyrKbd, key, FALSE);
break;
}
}
} }
static void static void
@ -998,6 +980,7 @@ ephyrPoll(void)
if (!ephyrKbd || if (!ephyrKbd ||
!((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled) !((EphyrKbdPrivate *)ephyrKbd->driverPrivate)->enabled)
continue; continue;
ephyrUpdateModifierState(ev.key_state);
KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE); KdEnqueueKeyboardEvent (ephyrKbd, ev.data.key_up.scancode, TRUE);
break; break;