X11

2016-07-24 12 views
5

का उपयोग कर लिनक्स पर कीकोड की बजाय स्कैनोड प्राप्त करें। मैं कीबोर्ड इनपुट (एक्स 11 इवेंट लूप का उपयोग करके) सुनने और स्कैनकोड प्राप्त करने की कोशिश कर रहा हूं। इन स्कैनकोडों को उस प्रकार के चरित्र के बजाय, कुंजी के भौतिक स्थान का संदर्भ लेना चाहिए। समस्या यह है कि, मैं जो कुछ भी प्राप्त कर सकता हूं वह कुंजी शब्द और कीकोड हैं, जो अलग-अलग भाषाओं के लिए अलग-अलग मैप किए जाते हैं (उदाहरण के लिए QWERTY बनाम QWERTZ)।X11

मेरा वर्तमान समाधान "/ usr/share/X11/xkb/keycodes/evdev" फ़ाइल को पढ़ने के लिए है। इसमें प्रमुख स्थानों के प्रमुख स्थानों की मैपिंग शामिल है। इसका उपयोग करके मैं किसी भी कुंजीकोड को स्कैनकोड पर वापस अनुवाद कर सकता हूं। मेरा अनुमान है कि यह चीजों को करने का एक स्थिर तरीका नहीं है। मैं लिनक्स के बारे में बहुत कुछ नहीं जानता। यही कारण है कि मैंने सोचा कि यहां पूछना एक अच्छा विचार हो सकता है।

क्या यह मानना ​​सुरक्षित है कि इन उपयोगकर्ता के मशीनों द्वारा इन evdev मैपिंग का उपयोग किया जा रहा है? यदि नहीं, तो मुझे मुख्य मैपिंग कहां मिल सकती हैं जिनका वास्तव में उपयोग किया जा रहा है? या क्या यह सब के लिए एक बेहतर समाधान है?

+1

यह विचार कि एक कुंजी का एक निश्चित भौतिक स्थान चरित्र इनपुट के एक विशेष कार्यान्वयन पर निर्भर करता है। लोग वर्चुअल कीबोर्ड का उपयोग कर सकते हैं जहां वे स्वयं कुंजी को पुनर्व्यवस्थित करने के लिए स्वतंत्र हैं। या हस्तलिखित इनपुट या आवाज पहचान या ... इनमें से किसी भी मामले में, चाबियों से जुड़े कोई भौतिक स्थान नहीं हैं।यहां तक ​​कि यदि स्कैनकोड के साथ एक भौतिक कीबोर्ड है, तो कई असंगत मॉडल हैं, अन्य फ़ाइलों को '/ usr/share/X11/xkb/keycodes' में देखें। –

+0

यह समझ में आता है। आइए मान लें कि हम पारंपरिक कीबोर्ड के अलावा किसी विशेष इनपुट विधियों को अनदेखा करते हैं। यदि मैपिंग के लिए "/ usr/share/X11/xkb/keycodes" में से किसी भी फाइल का उपयोग किया जा सकता है, तो क्या यह पता लगाने का कोई तरीका है कि उनमें से किस डिवाइस का उपयोग किया जाता है? – ComfyS

+0

कीबोर्ड ज्यामिति की जांच करके आप कुंजी के भौतिक स्थान प्राप्त कर सकते हैं। 'Setxkbmap -print -verbose 10' चलाएं और आप एक ज्यामिति में कथन शामिल देखेंगे। X11/xkb/ज्यामिति में फ़ाइलों की जांच करें (शायद सबसे अधिक "पीसी" नाम दिया गया है)। आप यह भी देखेंगे कि कौन सा मैपिंग उपयोग में है। मैं 'setxkbmap -print' के समतुल्य प्रोग्रामैटिक नहीं जानता लेकिन निश्चित रूप से एक है। मुझे यकीन नहीं है कि क्या होता है यदि उपयोगकर्ता xmodmap के साथ अपना कीबोर्ड रीमेप्स करता है, लेकिन मैं कहूंगा कि उन्हें इससे निपटने दें। –

उत्तर

3

मुझे एक ही समस्या थी और मुझे अभी एक समाधान मिला है। चलो पहले स्पष्ट के साथ शुरू करते हैं।

यदि आप "डब्ल्यू" या "4" जैसी विशिष्ट कुंजी प्राप्त करना चाहते हैं, चाहे वे कहीं भी स्थित हों, आप ईवेंट से प्राप्त की गई कुंजीकोड को केवल KeySym में परिवर्तित कर सकते हैं। इस मामले में "डब्ल्यू" XK_W और XK_w और "4" XK_4 (और अधिकांश कीबोर्ड पर XK_dollar) है।

लेकिन, कभी कभी आप जैसे "n वें मीटर वें पंक्ति के कुंजी" कुंजी प्राप्त करना चाहते हैं। ऐसा करने के लिए आपको महत्वपूर्ण नामों की आवश्यकता है। इस मामले में "डब्ल्यू" AD02 है और QWERTY कीबोर्ड पर "4" AE04 है।

मान लें कि आप एक ऐसा गेम बना रहे हैं जिसमें खिलाड़ी को स्थानांतरित करने के लिए WASD कुंजी का उपयोग करने की आवश्यकता हो। यदि आप कुंजी शब्दकोष देखते हैं तो यह क्यूडब्लूटीटीई कीबोर्ड पर ठीक काम करने जा रहा है, लेकिन अन्य कीबोर्ड लेआउट जैसे कि एज़र्टी, क्यूडब्लूटीटीजेड और डीवीओआरएके का उपयोग करने वाले लोग परेशानी करेंगे। तो इस मामले में महत्वपूर्ण नामों का उपयोग करना बेहतर है।

कुंजी नाम का उपयोग करना वास्तव में बहुत आसान है, लेकिन documentation बहुत गंदा है (लेकिन मैं अभी भी आप इसे पर एक नज़र डालें सलाह देते हैं)। मुझे GLFW के स्रोत कोड (विशेष रूप से src/x11_init.c) पर एक नज़र डालना पड़ा क्योंकि मैं अनजान था। इस विधि को एक्सकेबी की आवश्यकता है, लेकिन आप पहले से ही इसका इस्तेमाल कर रहे थे इसलिए मुझे लगता है कि कोई समस्या नहीं है।

सबसे पहले आपको कीबोर्ड मानचित्र प्राप्त करने और प्रतीकात्मक नाम प्राप्त करने की आवश्यकता है। हम केवल प्रमुख नाम चाहते हैं ताकि हम XkbKeyNamesMask का उपयोग कर सकें।

#include <X11/XKBlib.h> 

XkbDescPtr KbDesc = XkbGetMap(XDisplay, 0, XkbUseCoreKbd); 
XkbGetNames(XDisplay, XkbKeyNamesMask, KbDesc); 

फिर, घटना पाश में आप एक विशिष्ट कीकोड के लिए कुंजी नाम पाने के लिए KbDesc-> names-> कुंजी सरणी का उपयोग कर सकते हैं:

XEvent Event; 
XNextEvent(XDisplay, &Event); 

switch (Event.type) 
{ 
case KeyPress: 
    /* I'm not sure this 'if' is necessary, but better safe than sorry */ 
    if ((Event.xkey.keycode >= KbDesc->min_key_code) && (Event.xkey.keycode <= KbDesc->max_key_code)) 
    { 
     /* Copy key name into Name */ 
     char Name[XkbKeyNameLength + 1]; 
     memcmp(Name, KbDesc->names->keys[Event.xkey.keycode].name, XkbKeyNameLength); 
     Name[XkbKeyNameLength] = '\0'; /* Null terminator */ 

     if (strcmp(Name, "AD02") == 0) /* Is it W (for QWERTY and QWERTZ)/Z (for AZERTY)/comma (for DVORAK)/ц (for Russian) etc... ? */ 
     { 
      /* Do something... */ 
     } 
     else if (strcmp(Name, "AE04") == 0) /* Is it 4 (for most keyboards)/whatever's in its place? */ 
     { 
      /* Do something... */ 
     } 
     /* ... */ 
    } 

    /* ... */ 
} 

और बस हो गया। ऐसा लगता है कि अब तक बहुत अच्छी तरह से काम कर रहा है। मैं उल्लेख करना चाहता हूं कि विशेष कुंजी के बहुत अलग कुंजी नाम हैं। उदाहरण के लिए, बाएं शिफ्ट LFSH है, बाएं नियंत्रण LCTL है, अंतरिक्ष SPCE है और एस्केप ESC है।

मुझे उम्मीद है कि यह मदद करता है।

संबंधित मुद्दे