2010-10-27 10 views
24

के साथ ग्लोबल हॉटकी मेरा लक्ष्य एक प्रोग्राम है जो पृष्ठभूमि में सोता है लेकिन उपयोगकर्ता द्वारा कुछ "हॉटकी" के माध्यम से सक्रिय किया जा सकता है। Xlib मैनुअल और Xlib O'reilly मैनुअल के आसपास खुदाई से, मैं इकट्ठा करता हूं कि इसका सही तरीका XGrabKey के साथ है। हालांकि प्रक्रिया की मेरी समझ गलत है क्योंकि अवधारणा का एक सरल सबूत काम नहीं करता है।एक्स 11/एक्सलिब

मेरे समझ है कि अगर मैं grab_window के रूप में जड़ खिड़की के साथ XGrabKey कहते हैं, और owner_events झूठी है, तो जब भी अपने हॉटकी दबाया जाता है घटना केवल जड़ खिड़की के पास भेजा जाएगा है। यदि मैं रूट विंडो से कीप्रेस घटनाओं का चयन करता हूं, और उसके बाद एक्स घटनाओं को सुनता हूं, तो हॉटकी दबाए जाने पर मुझे एक महत्वपूर्ण प्रेस ईवेंट प्राप्त करना चाहिए। मैंने नीचे एक न्यूनतम उदाहरण चिपकाया है।

मुझे उम्मीद है कि जब प्रोग्राम चलाया जाता है, चाहे खिड़की पर ध्यान केंद्रित न हो, यदि Ctrl + Shift + K दबाया जाता है, तो मेरे प्रोग्राम को "हॉट कुंजी दबाया जाना चाहिए"! कंसोल में, और फिर समाप्त करें।

इसके अलावा, यह मेरी समझ है कि यदि XGrabKey विफल रहता है, तो डिफ़ॉल्ट त्रुटि हैंडलर एक संदेश प्रदर्शित करेगा, और चूंकि यह नहीं लगता कि कॉल सफल हो गया है।

जाहिर है, मेरी समझ किसी भी तरह से त्रुटिपूर्ण है। क्या कोई मुझे सही दिशा दिखा सकता है?

#include <iostream> 
#include <X11/Xlib.h> 
#include <X11/Xutil.h> 


using namespace std; 


int main() 
{ 
    Display* dpy  = XOpenDisplay(0); 
    Window  root = DefaultRootWindow(dpy); 
    XEvent  ev; 

    unsigned int modifiers  = ControlMask | ShiftMask; 
    int    keycode   = XKeysymToKeycode(dpy,XK_Y); 
    Window   grab_window  = root; 
    Bool   owner_events = False; 
    int    pointer_mode = GrabModeAsync; 
    int    keyboard_mode = GrabModeAsync; 

    XGrabKey(dpy, keycode, modifiers, grab_window, owner_events, pointer_mode, 
      keyboard_mode); 

    XSelectInput(dpy, root, KeyPressMask); 
    while(true) 
    { 
     bool shouldQuit = false; 
     XNextEvent(dpy, &ev); 
     switch(ev.type) 
     { 
      case KeyPress: 
       cout << "Hot key pressed!" << endl; 
       XUngrabKey(dpy,keycode,modifiers,grab_window); 
       shouldQuit = true; 

      default: 
       break; 
     } 

     if(shouldQuit) 
      break; 
    } 

    XCloseDisplay(dpy); 
    return 0; 
} 
+2

अपने कोड में आप का उपयोग 'XK_Y', आप कर सकते हैं इसके बजाय 'XK_K' कहना चाहते हैं? –

उत्तर

19

आपका प्रोग्राम यहां काम करता है। मेरा अनुमान है कि आपके पास एक और संशोधक सक्रिय है, जैसे न्यूमॉक। ग्रैकेकी केवल सटीक संशोधक मास्क पर काम करता है।

https://github.com/engla/keybinder:

उदाहरण यहाँ के लिए कुछ (GPL) मेटासिटी विंडो प्रबंधक

/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */ 
static void 
meta_change_keygrab (MetaDisplay *display, 
        Window  xwindow, 
        gboolean  grab, 
        int   keysym, 
        unsigned int keycode, 
        int   modmask) 
{ 
    unsigned int ignored_mask; 

    /* Grab keycode/modmask, together with 
    * all combinations of ignored modifiers. 
    * X provides no better way to do this. 
    */ 

    meta_topic (META_DEBUG_KEYBINDINGS, 
       "%s keybinding %s keycode %d mask 0x%x on 0x%lx\n", 
       grab ? "Grabbing" : "Ungrabbing", 
       keysym_name (keysym), keycode, 
       modmask, xwindow); 

    /* efficiency, avoid so many XSync() */ 
    meta_error_trap_push (display); 

    ignored_mask = 0; 
    while (ignored_mask <= display->ignored_modifier_mask) 
    { 
     if (ignored_mask & ~(display->ignored_modifier_mask)) 
     { 
      /* Not a combination of ignored modifiers 
      * (it contains some non-ignored modifiers) 
      */ 
      ++ignored_mask; 
      continue; 
     } 

     if (meta_is_debugging()) 
     meta_error_trap_push_with_return (display); 
     if (grab) 
     XGrabKey (display->xdisplay, keycode, 
        modmask | ignored_mask, 
        xwindow, 
        True, 
        GrabModeAsync, GrabModeSync); 
     else 
     XUngrabKey (display->xdisplay, keycode, 
        modmask | ignored_mask, 
        xwindow); 

     if (meta_is_debugging()) 
     { 
      int result; 

      result = meta_error_trap_pop_with_return (display, FALSE); 

      if (grab && result != Success) 
      {  
       if (result == BadAccess) 
       meta_warning (_("Some other program is already using the key %s with modifiers %x as a binding\n"), keysym_name (keysym), modmask | ignored_mask); 
       else 
       meta_topic (META_DEBUG_KEYBINDINGS, 
          "Failed to grab key %s with modifiers %x\n", 
          keysym_name (keysym), modmask | ignored_mask); 
      } 
     } 

     ++ignored_mask; 
    } 

    meta_error_trap_pop (display, FALSE); 
} 
+4

ओह मैन। आप बिल्कुल सही कह रहे है। न्यू लॉक चालू था। बहुत बहुत धन्यवाद। मैंने आज अपनी मूर्खता पर कुछ घंटे बर्बाद कर दिए हैं, लेकिन मुझे लगता है कि आपने मुझे कई और बर्बाद करने से बचाया है। – cheshirekow

8

से कोड आप/लक्ष्यीकरणका उपयोग कर X11 पर जीटीके कर रहे हैं है, वहाँ एक बहुत सरल इंटरफेस के साथ एक सी पुस्तकालय है

में पाइथन, लुआ और वाला बाइंडिंग शामिल हैं। (here का भी उल्लेख किया गया है।)

+1

एक अच्छी पुस्तकालय। आपके लिए +1 धन्यवाद :-) – madper

7

अपने मुखौटा ControlMask | ShiftMask के साथ यदि कोई अन्य संशोधक कुंजी आयोजित की जाती है तो आपको कुंजी नहीं मिल जाएगी। यह पहली जगह ठीक लगता है, लेकिन एक गड़बड़ी है: न्यूमॉक, कैप्सलॉक और समान रूप से सभी को संशोधक के रूप में भी माना जाता है।

आपके पास दो विकल्प:।

  • आप XGrabKey() कई बार, एक बार प्रत्येक स्पष्ट संयोजन है कि आप में रुचि रखते हैं के लिए कॉल
  • आप AnyModifier साथ XGrabKey() फोन और event.xkey.state का उपयोग की जाँच करने के संशोधक हैं या नहीं जैसा कि आप उम्मीद करते थे।

हेडर फाइल <X.h>ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask और AnyModifier परिभाषित करता है।

चाबियाँ हैं:

Mask  | Value | Key 
------------+-------+------------ 
ShiftMask |  1 | Shift 
LockMask |  2 | Caps Lock 
ControlMask |  4 | Ctrl 
Mod1Mask |  8 | Alt 
Mod2Mask | 16 | Num Lock 
Mod3Mask | 32 | Scroll Lock 
Mod4Mask | 64 | Windows 
Mod5Mask | 128 | ??? 

चेतावनी मैं कोशिश कर रहा द्वारा ModNMask चाबियाँ बारे में पता चला और अगर यह सभी मशीनों/विन्यास/संस्करणों/ऑपरेटिंग सिस्टम पर मान्य है मैं नहीं जानता।

अपने मामले में, आप शायद यह सुनिश्चित करना चाहते हैं कि ShiftMask | CtrlMask सेट है, Mod1Mask | Mod4Mask स्पष्ट हैं, और अन्य को अनदेखा किया जाना है।

मैं कुंजी हड़पने सेटअप करने के लिए ऐसा करते हैं चाहते हैं:

XGrabKey(dpy, keycode, AnyModifier, grab_window, owner_events, pointer_mode, keyboard_mode); 

और यह जाँच करने के लिए है कि क्या सही संशोधक सेट कर रहे हैं:

switch (ev.type) { 
case KeyPress: 
    if ((ev.xkey.state & (ShiftMask | CtrlMask | Mod1Mask | Mod4Mask)) == (ShiftMask | CtrlMask)) 
     // ... 
} 
+2

मूल्य '128' मेरे सिस्टम पर __ISO_Level3_Shift__ से मेल खाता है। –