2012-07-03 5 views
6

मैं सभी आने वाली कुंजी दबाए गए ईवेंट रिकॉर्ड करना चाहता हूं इससे कोई फर्क नहीं पड़ता कि विंडो किस फोकस में है या पॉइंटर कहां है।एक्स कुंजीपटल/रिलीज इवेंट्स फोकस में विंडो के बावजूद कैप्चरिंग

मैंने एक नमूना कोड लिखा है जो फोकस में वर्तमान विंडो की प्रमुख दबाए गए ईवेंट को कैप्चर करना चाहिए।

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <locale.h> 
#include <stdint.h> 
#include <stdarg.h> 
#include <errno.h> 
#include <pthread.h> 
#include <X11/Xlib.h> 
#include <X11/Xos.h> 
#include <X11/Xfuncs.h> 
#include <X11/Xutil.h> 

#include <X11/Xatom.h> 
int _invalid_window_handler(Display *dsp, XErrorEvent *err) { 
    return 0; 
} 

int main() 
{ 
    Display *display = XOpenDisplay(NULL); 
    int iError; 
    KeySym k; 
    int revert_to; 
    Window window; 
    XEvent event; 
    Time time; 
    XSetErrorHandler(_invalid_window_handler); 
    XGetInputFocus(display, &window, &revert_to); 
    XSelectInput(display, window, KeyPressMask | KeyReleaseMask); 
    iError = XGrabKeyboard(display, window, 
          KeyPressMask | KeyReleaseMask, 
          GrabModeAsync, 
          GrabModeAsync, 
          CurrentTime); 
    if (iError != GrabSuccess && iError == AlreadyGrabbed) { 
     XUngrabPointer(display, CurrentTime); 
     XFlush(display); 
     printf("Already Grabbed\n");  
    } else if (iError == GrabSuccess) { 
     printf("Grabbed\n"); 
    } 
    while(1) { 
      XNextEvent(display,&event); 
      switch (event.type) { 
       case KeyPress : printf("Key Pressed\n"); break; 
       case KeyRelease : printf("Key Released\n"); break; 
       case EnterNotify : printf("Enter\n"); break; 
      } 
    } 
    XCloseDisplay(display); 
    return 0; 
} 

मैं आवेदन जो खिड़की बनाई कीबोर्ड की घटनाओं को पहले से ही पकड़ लिया हो सकता है के रूप में कुंजीपटल पर कब्जा करने के XGrabKeyboard बोल रहा हूँ। उपर्युक्त कोड के साथ मैं कीबोर्ड को पकड़ने में सक्षम हूं लेकिन कीबोर्ड लूप के अंदर कीबोर्ड पर किसी भी कुंजी के लिए कुंजीपटल या कीरलीज़ इवेंट्स प्राप्त करने में असमर्थ हूं। क्या ऐसी कोई चीज है जिसे मैं कोड में याद कर रहा हूं जिसके कारण मैं घटनाएं प्राप्त करने में असमर्थ हूं? किसी भी सहायताको बहुत सराहा जाएगा।

मेरा अंतिम उद्देश्य विंडो पर ध्यान केंद्रित करने के बावजूद स्क्रीन पर महत्वपूर्ण प्रेस ईवेंट कैप्चर करना है। कोड को पठनीय करने के लिए मैंने फोकस में केवल विंडो के लिए नमूना कोड दिया है। मैं सभी विंडोज़ प्राप्त करने के लिए XQueryTree करता हूं और अपेक्षित परिणाम प्राप्त करने के लिए ऊपर दिए गए एक ही तर्क को लागू करता हूं।

+0

क्यों तो घटना सबसिस्टम का उपयोग नहीं? –

+0

क्या आप घटना उपप्रणाली पर विस्तृत जानकारी दे सकते हैं? मैंने XSelectInput पर कॉल में कैप्चर करने के लिए ईवेंट के रूप में KeyPressMask, KeyReleaseMask दिया है। धन्यवाद –

+0

इग्नासिओ वाज़्यूज़-एब्राम लिनक्स कर्नेल इनपुट उपप्रणाली को संदर्भित करता है, जो '/ dev/input /' में वर्ण उपकरणों के माध्यम से सुलभ है। यह एक्स को पूरी तरह से बाईपास करता है, और सीधे एचआईडी घटनाओं को कर्नेल से प्राप्त करता है - लेकिन रूट विशेषाधिकारों की भी आवश्यकता होती है। –

उत्तर

4

कीबोर्ड पर कब्जा करने में सक्षम होने के लिए आपको मैप किए गए विंडो की आवश्यकता है।

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

int main() 
{ 
    Display *display; 
    Window window, rootwindow; 
    XEvent event; 
    KeySym escape; 

    display = XOpenDisplay(NULL); 
    rootwindow = DefaultRootWindow(display); 
    window = XCreateWindow(display, rootwindow, 
          -99, -99, 1, 1, /* x, y, width, height */ 
          0, 0, InputOnly, /* border, depth, class */ 
          CopyFromParent, /* visual */ 
          0, NULL); /* valuemask and attributes */ 

    XSelectInput(display, window, StructureNotifyMask | SubstructureRedirectMask | ResizeRedirectMask | KeyPressMask | KeyReleaseMask); 
    XLowerWindow(display, window); 
    XMapWindow(display, window); 

    do { 
     XNextEvent(display, &event); 
    } while (event.type != MapNotify); 

    XGrabKeyboard(display, window, False, GrabModeAsync, GrabModeAsync, CurrentTime); 
    XLowerWindow(display, window); 

    escape = XKeysymToKeycode(display, XK_Escape); 
    printf("\nPress ESC to exit.\n\n"); 
    fflush(stdout); 

    while (1) { 

     XNextEvent(display, &event); 

     if (event.type == KeyPress) { 
      printf("KeyPress: keycode %u state %u\n", event.xkey.keycode, event.xkey.state); 
      fflush(stdout); 

     } else 
     if (event.type == KeyRelease) { 

      printf("KeyRelease: keycode %u state %u\n", event.xkey.keycode, event.xkey.state); 
      fflush(stdout); 

      if (event.xkey.keycode == escape) 
       break; 
     } else 
     if (event.type == UnmapNotify) { 

      XUngrabKeyboard(display, CurrentTime); 
      XDestroyWindow(display, window); 
      XCloseDisplay(display); 

      display = XOpenDisplay(NULL); 
      rootwindow = DefaultRootWindow(display); 
      window = XCreateWindow(display, rootwindow, 
            -99, -99, 1, 1, /* x, y, width, height */ 
            0, 0, InputOnly, /* border, depth, class */ 
            CopyFromParent, /* visual */ 
            0, NULL); /* valuemask and attributes */ 

      XSelectInput(display, window, StructureNotifyMask | SubstructureRedirectMask | ResizeRedirectMask | KeyPressMask | KeyReleaseMask); 
      XLowerWindow(display, window); 
      XMapWindow(display, window); 

      do { 
       XNextEvent(display, &event); 
      } while (event.type != MapNotify); 

      XGrabKeyboard(display, window, False, GrabModeAsync, GrabModeAsync, CurrentTime); 
      XLowerWindow(display, window); 

      escape = XKeysymToKeycode(display, XK_Escape); 

     } else { 

      printf("Event type %d\n", event.type); 
      fflush(stdout); 
     } 
    } 

    XUngrabKeyboard(display, CurrentTime); 

    XDestroyWindow(display, window); 
    XCloseDisplay(display); 
    return 0; 
} 

यह एक छोटी सी खिड़की (मैं भी इसके लिए एक शीर्षक सेट करने के लिए परेशान नहीं किया था) यह खिड़की ढेर के नीचे करने के लिए कम करती है, तो यह किसी भी मौजूदा खिड़कियों के पीछे चला जाता है का उपयोग करता है: यहाँ अवधारणा का एक सबूत है। खिड़की सजावट रहित और पारदर्शी, या प्रतीक बनाने के लिए आप खिड़की प्रबंधक (डब्ल्यूएम) के साथ संवाद कर सकते हैं, ताकि स्क्रीन पर कोई दृश्य विंडो न हो; उपरोक्त कोड परेशान नहीं करता है।

मैं जिस चाल का उपयोग करता हूं वह यह है कि जब भी उपयोगकर्ता विंडो को अनैप करने का प्रबंधन करता है - कहें, किसी अन्य कार्यक्षेत्र पर जाकर - कोड पुरानी विंडो को नष्ट कर देता है, एक नया बनाता है, और कीबोर्ड को फिर से पकड़ता है। यह किसी भी keypresses खोने के लिए पर्याप्त तेज़ होना चाहिए। ऐसा करने के अन्य तरीके हो सकते हैं, लेकिन मुझे संदेह है कि उन्हें विंडो प्रबंधक के साथ निकट संपर्क की आवश्यकता है।

ध्यान दें कि मुझे वास्तव में कुंजीपटल को लगातार पकड़ने की आवश्यकता नहीं है, इसलिए उपरोक्त दृष्टिकोण संभवतः सबसे आसान नहीं है। यह सिर्फ एक दृष्टिकोण था जो मुझे लगता है कि काम करता है; बेहतर संभावना है।

+1

कुंजीपटल घटनाओं को कैप्चर करने का कोई तरीका है जबकि उन्हें शेष एक्स अनुप्रयोगों द्वारा प्राप्त किया जा रहा है? –

+3

वर्तमान इनपुट फोकस वाले विंडो में हथियार कुंजीपटल ईवेंट भेजने के लिए आप 'XSendEvent (डिस्प्ले, इनपुट फ़ोकस, ट्रू, कीप्रेसमास्क | कीरलीज़मास्क, इवेंट)' का उपयोग कर सकते हैं, लेकिन यह आमतौर पर गलत दृष्टिकोण है। यदि आप सभी कीप्रेसों की निगरानी करना चाहते हैं, * * नहीं * मैं एक के लिए कीबोर्ड स्नीफर्स पसंद नहीं करता हूं। यह देखने के लिए कि कैसे हॉटकी/ऑटोकी आमतौर पर लागू होते हैं, उदाहरण के लिए देखें। 'GtkHotKey' या' libtomboy/tomboykeybinder.c'; वे रूट विंडो पर विशिष्ट कुंजी लेते हैं (यानी जब अन्य विंडो द्वारा नियंत्रित नहीं किया जाता है), और यह सही है। –

+1

धन्यवाद!सिर्फ रिकॉर्ड के लिए, मैं यह सुनिश्चित करने के लिए सभी प्रमुख प्रेसों की निगरानी करना चाहता हूं कि मेरा पुराना कीबोर्ड मुझ पर कोई चाल नहीं चला रहा है। –

3

निम्न आदेश कंसोल के लिए पूरे एक्स सत्र की सभी घटनाओं की एक सूची प्रिंट होगा:

$ xinput test-xi2 --root 

उदाहरण आउटपुट:

⎡ Virtual core pointer      id=2 [master pointer (3)] 
⎜ ↳ Virtual core XTEST pointer    id=4 [slave pointer (2)] 
⎜ ↳ USB Mouse         id=10 [slave pointer (2)] 
⎜ ↳ MCE IR Keyboard/Mouse (ite-cir)   id=11 [slave pointer (2)] 
⎣ Virtual core keyboard      id=3 [master keyboard (2)] 
    ↳ Virtual core XTEST keyboard    id=5 [slave keyboard (3)] 
    ↳ Power Button        id=6 [slave keyboard (3)] 
    ↳ Video Bus         id=7 [slave keyboard (3)] 
    ↳ Power Button        id=8 [slave keyboard (3)] 
    ↳ Oracle USB Keyboard      id=9 [slave keyboard (3)] 
    ↳ ITE8713 CIR transceiver     id=12 [slave keyboard (3)] 
EVENT type 14 (RawKeyRelease) 
    device: 3 (9) 
    detail: 36 
    valuators: 

EVENT type 3 (KeyRelease) 
    device: 9 (9) 
    detail: 36 
    flags: 
    root: 1324.55/821.81 
    event: 1324.55/821.81 
    buttons: 
    modifiers: locked 0x10 latched 0 base 0 effective: 0x10 
    group: locked 0 latched 0 base 0 effective: 0 
    valuators: 
    windows: root 0x9c event 0x9c child 0x7291d5 
EVENT type 15 (RawButtonPress) 
    device: 2 (10) 
    detail: 1 
    valuators: 
    flags: 

EVENT type 4 (ButtonPress) 
    device: 10 (10) 
    detail: 1 
    flags: 
    root: 1324.55/821.81 
    event: 1324.55/821.81 
    buttons: 
    modifiers: locked 0x10 latched 0 base 0 effective: 0x10 
    group: locked 0 latched 0 base 0 effective: 0 
    valuators: 
    windows: root 0x9c event 0x9c child 0x7291d5 
EVENT type 16 (RawButtonRelease) 
    device: 2 (10) 
    detail: 1 
    valuators: 
    flags: 
संबंधित मुद्दे