How to get a num lock state using C/C++?

2019-03-31 18:53发布

问题:

I have read Gdk forum link which says that getting num lock state api is implemented since version 3.0. But I am using version 2.4 and I cannot update to version 3.0 as I need to support lower Linux version. Here is the discussion link:

http://mail.gnome.org/archives/commits-list/2010-July/msg00259.html

SO, is there any other way to get the num lock state using internal Linux command?

Regards, iSight

回答1:

Sample code to get the NumLock state. Let foo.c be:

#include <stdio.h>
#include <X11/Xlib.h>

int main(void) {  
   Display *dpy = XOpenDisplay(":0"); 
   XKeyboardState x;
   XGetKeyboardControl(dpy, &x);
   XCloseDisplay(dpy);
   printf("led_mask=%lx\n", x.led_mask);
   printf("NumLock is %s\n", (x.led_mask & 2) ? "On" : "Off");
   return 0;
}

Then this gives, tested with CentOS 5 on a Dell laptop:

gcc foo.c -o foo -lX11
foo
led_mask=2
NumLock is On

Or you could do something with popen("xset q | grep LED");.

The second bit of the mask is fairly common for NumLock, but I don't believe it is guaranteed.

Original answer: A good starting point is xev, available for about 20 years:

   xev

And you can decode key events via:

foobar (XKeyEvent *bar) {
   char dummy[20];
   KeySym key;
   KeySym keyKeypad;
   XLookupString(bar, dummy, sizeof dummy, &key, 0);
   keyKeypad = XKeycodeToKeysym(..., bar->keycode, NUMLOCK_Mask);
   if (IsKeypadKey(keyKeypad))
      ...;
   // ...
}


回答2:

You can use this linux command to do it

{ if (num_lock == 0) system("setleds -F +num"); else if num_lock == 1) ; //do nothing }



回答3:

I did some sniffing around, and I found a possible implementation with ioctl.h that polls the keyboard state and tests that against a couple of flags.

Take a look at this form post's implementation, and replace K_CAPSLOCK with K_NUMLOCK*. It's pretty fugly, but it can easily be wrapped in a function and tucked away.

*The reason for the replacement on the post was because of an old bug where caps lock and num lock were accidentally reversed. It should be fixed now.



回答4:

I have checked the hard ware key code. Whenever num lock is on and pressed the number key at num pad i compare the hard ware key code which is universally constant to all manufacturer. Hence, I don't need to use ioctl.h header.



回答5:

If you don't care about the Numlock state "while nothing is happening", and only when e.g. a keypress happens, the lowest overhead way is this.

For some XKeyEvent *xke

bool numlock = ((xke->state & Mod2Mask) == Mod2Mask);

For GDK, you might need something like Gdk.FilterFunc to get the xevent. Check xevent->type.

#include <Xlib.h>
XEvent = (XEvent *) &xevent // from Gdk.FilterFunc
int type = event ->type;
switch(type) {
    case KeyPress:
    case KeyRelease:
        do_something_with((XKeyEvent *) event);
        break;
}


标签: c++ c linux gtk x11