Newsgroup: it.comp.lang.c
Titolo: resupero stato caps-lock/num-lock/scroll-lock

Salve a tutti, ho scritto un programmino in Java che notifica in modo visuale la pressione dei tasti caps-num-scroll lock. Dal momento che Java non possiede un metodo valido per "ascoltare" la pressione dei tasti senza che l'applicazione lanciata possieda il focus ho dovuto ricorrere all'interfaccia nativa tramite il linguaggio C.
 
Ho scritto un semplice programmino (basandomi su un esempio recuperato in rete) che alla pressione dei tasti notifica un metodo in Java. All'avvio dell'applicazione Java lancia questo programmino che ascolta i tasti premuti dall'utente e se questi corrispondono a quelli definiti notifica al programma in Java il tasto premuto.
 
Funziona tuttio correttamente ma avrei bisogno di conoscere lo stato dei tasti (preuto o no) all'avvio dell'applicazione. Qualcuno di voi conosce un modo in C (utilizzando le librerie grafiche di X) di assolvere questo compito?
 
 
 
 
==============================================================
 
#include <X11/Xlib.h>
#include "com_net_biz_org_reddy_utils_jkeyled_JKeyLed.h"
#include <stdio.h>
#include <stdlib.h>
 
JNIEXPORT jint JNICALL Java_com_net_biz_org_reddy_utils_jkeyled_JKeyLed_listen(JNIEnv *env, jobject obj) {
 
 char *className = "com/net/biz/org/reddy/utils/jkeyled/JKeyLed";
 char *methodName = "fire_key_event";
 
 // cerca la classe da caricare
 jclass cls = (*env)->FindClass(env, className);
 if (cls == NULL) {
  printf("cannot find class %s\n", className);
  return EXIT_FAILURE;
 }
 
 // cerca il metodo da invocare
 jmethodID mid = (*env)->GetMethodID(env, cls, methodName, "(I)V");
 if (mid == 0) {
  printf("cannot find method %s\n", methodName);
  return EXIT_FAILURE;
 }
 
 Display * dpy = XOpenDisplay(0);
 
 if (!dpy) {
  printf("Cannot open display");
  return EXIT_FAILURE;
 }
 
 Window root = DefaultRootWindow(dpy);
 XEvent ev;
 
 // definisce i tasti da trappare
 char * capslock_key_string = "Caps_Lock";
 char * numlock_key_string = "Num_Lock";
 char * scrolllock_key_string = "Scroll_Lock";
 
 // per ottenere i codici dei tasti consultare il file X11/keysymdef.h
 // (
http://tronche.com/gui/x/xlib/utilities/keyboard/XStringToKeysym.html
)
 
 KeyCode capslock_key = XKeysymToKeycode(dpy, XStringToKeysym(capslock_key_string));
 KeyCode numlock_key = XKeysymToKeycode(dpy, XStringToKeysym(numlock_key_string));
 KeyCode scrolllock_key = XKeysymToKeycode(dpy, XStringToKeysym(scrolllock_key_string));
 
 XGrabKey(dpy, capslock_key, AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
 XGrabKey(dpy, numlock_key, AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
 XGrabKey(dpy, scrolllock_key, AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
 
 for (;;) {
 
  XNextEvent(dpy, &ev);
 
  if (ev.type != KeyPress) {
   continue;
  }
 
  // notifica al runtime Java la pressione del tasto inviando il codice come parametro
  (*env)->CallIntMethod(env, obj, mid, ev.xkey.keycode);
 }
 
 return EXIT_SUCCESS;
 
}
 
==============================================================

> avrei bisogno di conoscere lo stato dei tasti (preuto o no) all'avvio dell'applicazione.
 
Ciao,
quello che ti serve e' semplicemente interrogare lo stato della
tastiera, prima di iniziare ad "ascoltare" gli eventi successivi.
Forse XkbGetState ti puo` essere utile.
-- 
andrea - ar italy, com

Ciao non è che potresti postare un piccolo esempio di funzionamento? Ho cercato su internet ma non ho trovato molto. e , in tutta sincerità, col c mi ci taglio un po'.


Sono riuscito a capire il funzionamento di XkbGetState, posto il listato del programmino semmai qualcuno avesse bisogno:
 
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include "com_net_biz_org_reddy_utils_jkeyled_JKeyLed.h"
#include <stdio.h>
#include <stdlib.h>
 
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include "com_net_biz_org_reddy_utils_jkeyled_JKeyLed.h"
#include <stdio.h>
#include <stdlib.h>
 
/* questa funzione viene invocata dall'interno della classe java com.net.biz.org.reddy.utils.jkeyled.JKeyLed */
JNIEXPORT jint JNICALL Java_com_net_biz_org_reddy_utils_jkeyled_JKeyLed_listen(JNIEnv *env, jobject obj) {
 
  // cerca la classe dell'oggetto che invocato il metodo
  jclass cls = (*env)->FindClass(env, "com/net/biz/org/reddy/utils/jkeyled/JKeyLed");
  if (cls == NULL ) {
    printf("cannot find class com/net/biz/org/reddy/utils/jkeyled/JKeyLed\n");
    return EXIT_FAILURE;
  }
 
  // cerca il metodo da invocare sull'oggetto (fireKeyEvent)
  jmethodID mid = (*env)->GetMethodID(env, cls, "fireKeyEvent", "(I)V");
  if (mid == 0) {
    printf("cannot find method fireKeyEvent\n");
    return EXIT_FAILURE;
  }
 
  // recupera una connessione con il server X e la finestra principale
  Display * dpy = XOpenDisplay(0);
  if (!dpy) {
    printf("Cannot open display");
    return EXIT_FAILURE;
  }
 
  Window root = DefaultRootWindow(dpy) ;
  XEvent ev;
 
  // definisce i tasti che il programma deve "ascoltare",
  // per ottenere i codici dei tasti consultare il file X11/keysymdef.h
  // (
http://tronche.com/gui/x/xlib/utilities/keyboard/XStringToKeysym.html
)
  KeyCode capslock_key = XKeysymToKeycode(dpy, XStringToKeysym("Caps_Lock"));
  KeyCode numlock_key = XKeysymToKeycode(dpy, XStringToKeysym("Num_Lock"));
  KeyCode scrolllock_key = XKeysymToKeycode(dpy, XStringToKeysym("Scroll_Lock"));
 
  // richiede al server X di ascoltare i tasti definiti
  XGrabKey(dpy, capslock_key, AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, numlock_key, AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, scrolllock_key, AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
 
  // recupera lo stato dei tasti
  XkbStateRec kbState;
  XkbGetState(dpy, XkbUseCoreKbd, &kbState);
 
  // cerca il metodo da invocare sull'oggetto (initStatus)
  jmethodID initStatusMid = (*env)->GetMethodID(env, cls, "initStatus", "(ZZZ)V");
  if (initStatusMid == 0) {
    printf("cannot find method initStatus\n");
    return EXIT_FAILURE;
  }
  // chiama l'inizializzazione indicando lo stato dei tasti CAPS_LOCK (codice 2) e
  // NUM_LOCK (codice 16), non riesco a capire che codice abbia lo SCROLL_LOCK
  // perche' con il DE Gnome lo SCROLL_LOCK non mi funziona
  (*env)->CallIntMethod(env, obj, initStatusMid, XkbModLocks(&kbState) & 2, XkbModLocks(&kbState) & 16, 0);
 
  // inizia l'ascolto
  for (;;) {
 
    // la pressione di ogni tasto richiama questa funzione e valorizza  l'evento (ev)
    XNextEvent(dpy, &ev);
 
    // controlla che l'evento generato sia la pressione di un tasto
    // (perche' ad esempio potrebbe essere il movimento del mouse)
    if (ev.type != KeyPress) {
      continue;
    }
 
    // invoca il metodo Java passando il codice del tasto premuto
    (*env)->CallIntMethod(env, obj, mid, ev.xkey.keycode);
  }
 
  return EXIT_SUCCESS;
 
}
 
 
============================================================================


 Ciao non è che potresti postare un piccolo esempio di funzionamento? Ho cercato su internet ma non ho trovato molto. e , in tutta sincerità, col c mi ci taglio un po'.
 
pensa se fosse stato C Sharp :)
 
scusate non ho resistito