discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

SHIFT keys on X11


From: Stéphane Goujet
Subject: SHIFT keys on X11
Date: Mon, 08 May 2006 15:08:19 +0300
User-agent: Mozilla Thunderbird 1.0.6 (Windows/20050716)

Hello,

I was about to post the solution of my problem with [NSEvent isARepeat],
but now I have a problem with the SHIFT modifier key.

  In a NSView, I have :

------------------------------------------------
-(void) flagsChanged:(NSEvent *) event {
  if(([event modifierFlags]&NSShiftKeyMask)==NSShiftKeyMask) {
    NSLog(@"SHIFT ON\n");
  } else {
    NSLog(@"SHIFT OFF\n");
  }
}
------------------------------------------------

  When I press the SHIFT key and then release it, on Cocoa, I get the
expected behaviour :
SHIFT ON
SHIFT OFF

  But on GNUstep/linux/X11, I get :
SHIFT OFF
SHIFT ON

  The reason of it is explained in back/Source/x11/XGServerEvent.m :

In the function process_key_event() :

------------------------------------------------
  /* Process modifiers */
  eventFlags = process_modifier_flags (xEvent->xkey.state);

  /* Add NSNumericPadKeyMask if the key is in the KeyPad */
  if (IsKeypadKey (keysym))
    eventFlags = eventFlags | NSNumericPadKeyMask;

  NSDebugLLog (@"NSKeyEvent", @"keysym=%d, keyCode=%d flags=%d
(state=%d)",
              keysym, keyCode, eventFlags, ((XKeyEvent *)xEvent)->state);

  /* Add NSFunctionKeyMask if the key is a function or a misc function key
*/
  /* We prefer not to do this and do it manually in process_char
     because X's idea of what is a function key seems to be different
     from OPENSTEP's one */
  /* if (IsFunctionKey (keysym) || IsMiscFunctionKey (keysym))
       eventFlags = eventFlags | NSFunctionKeyMask; */

  /* First, check to see if the key event if a Shift, NumLock or
     CapsLock or ShiftLock keypress/keyrelease.  If it is, then use a
     NSFlagsChanged event type.  This will generate a NSFlagsChanged
     event each time you press/release a shift key, even if the flags
     haven't actually changed.  I don't see this as a problem - if we
     didn't, the shift keypress/keyrelease event would never be
     notified to the application.

     NB - to know if shift was pressed, we need to check the X keysym
     - it doesn't work to compare the X modifier flags of this
     keypress X event with the ones of the previous one, because when
     you press Shift, the X shift keypress event has the *same* X
     modifiers flags as the X keypress event before it - only
     keypresses coming *after* the shift keypress will get a different
     X modifier mask.  */

  if (keysym_is_X_modifier (keysym))
    {
      eventType = NSFlagsChanged;
    }
------------------------------------------------

  The process_modifier_flags() function is as follows :

------------------------------------------------
// process_modifier_flags() determines which modifier keys (Command,
Control,
// Shift,  and so forth) were held down while the event occured.
static unsigned int
process_modifier_flags(unsigned int state)
{
  unsigned int eventModifierFlags = 0;

  if (state & ShiftMask)
    eventModifierFlags = eventModifierFlags | NSShiftKeyMask;

  if (state & LockMask)
    eventModifierFlags = eventModifierFlags | NSAlphaShiftKeyMask;

  if (_control_pressed != 0)
    eventModifierFlags = eventModifierFlags | NSControlKeyMask;

  if (_command_pressed != 0)
    eventModifierFlags = eventModifierFlags | NSCommandKeyMask;

  if (_alt_pressed != 0)
    eventModifierFlags = eventModifierFlags | NSAlternateKeyMask;

  // Other modifiers ignored for now.

  return eventModifierFlags;
}
------------------------------------------------

and the function keysym_is_X_modifier() is :

------------------------------------------------
static BOOL
keysym_is_X_modifier (KeySym keysym)
{
  switch (keysym)
    {
    case XK_Num_Lock:
    case XK_Shift_L:
    case XK_Shift_R:
    case XK_Caps_Lock:
    case XK_Shift_Lock:
      return YES;

    default:
      return NO;
    }
}
------------------------------------------------


  xEvent->xkey.state does not get updated when one presses the SHIFT key
but later, so it is updated when one releases that key, which causes the
"inverted" behaviour.
  Nevertheless, the needed information is available through the keysym,

  I made the following Q&D fix in process_key_event:

I added the variable

static unsigned shiftPressed=0;

and I replaced
------------------------------------------------
  if (keysym_is_X_modifier (keysym))
    {
      eventType = NSFlagsChanged;
    }
------------------------------------------------
by
------------------------------------------------
  if (keysym_is_X_modifier (keysym))
    {
    switch (keysym)
      {
      case XK_Shift_L:
      case XK_Shift_R:
        if(xEvent->xkey.type==KeyPress) {
          shiftpressed++;
        } else { // KeyRelease
          shiftpressed--;
        }
        if(shiftpressed) {
          eventFlags|= NSShiftKeyMask;
        } else {
          eventFlags&= ~NSShiftKeyMask;
        }
      default:
        break;
      }
      eventType = NSFlagsChanged;
    }
------------------------------------------------

 so that eventFlags (which will be available as [NSEvent modifierFlags])
reflect the real position of the SHIFT key.

  Do you see any bad side-effect of this change ?

Goodbye,
         Stéphane.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]