2025, Oct 08 07:31
Linux Mint Cinnamon में Super+V क्यों अटकता है और XRecord से लिस्निंग कैसे करें
Linux Mint Cinnamon में Super+V हॉटकी पहली दबाहट पर क्यों फेल होती है, और बिना ग्रैब किए XRecord से इसे सुनने का उपाय जानें.
Linux डेस्कटॉप पर ग्लोबल हॉटकीज़ आम तौर पर ठीक चलती हैं—जब तक Super कुंजी मैदान में नहीं आती। एक आम उदाहरण: किसी Python ऐप में Super+V बाँधने पर हैंडलर चलना चाहिए, लेकिन पहली दबाहट पर फोकस वाले टेक्स्ट फ़ील्ड में साधारण “v” टाइप हो जाता है। Alt+F3 जैसे अन्य संयोजन अपेक्षित रूप से काम करते हैं। नीचे बताया गया है कि Linux Mint 22.1 Cinnamon पर ऐसा क्यों होता है और डेस्कटॉप एनवायरनमेंट से ग्रैब छीने बिना Super+V को भरोसेमंद तरीके से कैसे कैप्चर करें।
समस्या को उजागर करने वाला न्यूनतम उदाहरण
नीचे दिया कोड gi.repository Keybinder के ज़रिए Super+V बाँधता है और एक Gtk एप्लिकेशन को चलाए रखता है। Super+V पहली बार दबाने पर सक्रिय टेक्स्ट एरिया में लोअरकेस “v” प्रिंट होता है; केवल उसके बाद साधारण “v” दबाने पर ही हैंडलर ट्रिगर होता है। Alt+F3 या इसी तरह के संयोजन यह व्यवहार नहीं दिखाते।
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Keybinder', '3.0')
from gi.repository import Keybinder, Gtk
class ClipService(Gtk.Application):
    def __init__(self):
        super().__init__(application_id="org.sample.keydemo", flags=0)
        self.connect("activate", self._on_activate)
        self.connect("startup", self._on_start)
    def _on_start(self, app):
        print("Application started.")
        self.hold()
    def _on_activate(self, app):
        pass
    def on_hotkey(self, user_data=None):
        print("Key was pressed!")
if __name__ == "__main__":
    svc = ClipService()
    Keybinder.init()
    Keybinder.bind("<Super>V", svc.on_hotkey)
    svc.run(None)
Super के साथ क्या हो रहा है
एक समय में केवल एक ही क्लाइंट ग्लोबल की ग्रैब का मालिक हो सकता है। Linux Mint में डेस्कटॉप मेनू आमतौर पर Super (अक्सर Mod4 के माध्यम से) का उपयोग करता है और उसे ग्रैब कर लेता है। जब कोई दूसरा प्रोग्राम उसी कॉम्बिनेशन को ग्रैब करने की कोशिश करता है, तो X सर्वर उसे अस्वीकार कर देता है—यदि आप Xlib की grab_key के साथ सीधे ग्रैब करें तो Xlib.error.BadAccess मिलता है। यह इस अवलोकन से मेल खाता है कि Super_L से बंधी “show menu” क्रिया को निष्क्रिय करने पर पहली बार Super+V काम करता है, और Keyboard → Shortcuts में Super+V असाइन करने पर भी पहली दबाहट आगे बढ़ जाती है। संक्षेप में, डेस्कटॉप पहले से ही ग्रैब का मालिक है; Super पर आधारित संयोजनों के लिए आपका प्रोसेस ग्रैब का मालिक न होने के कारण असंगत व्यवहार देखता है।
Alt+F3 जैसे अन्य मॉडिफ़ायर आमतौर पर इसलिए काम करते हैं क्योंकि उन्हें मेनू ने दावा नहीं किया होता, तो ग्रैब सफल हो जाता है और कॉलबैक अपेक्षित रूप से चलता है।
बिना ग्रैब किए सुनने का व्यावहारिक तरीका: XRecord
यदि कोई और घटक पहले से Super को ग्रैब कर चुका है, तो उससे टकराना बेकार है। इसकी बजाय निष्क्रिय रूप से सुनें। XRecord एक्सटेंशन आपकी प्रक्रिया तक कीबोर्ड ईवेंट्स का प्रतिबिंब भेजता है, बिना स्वामित्व लिए—मतलब आप Super+V का पता लगा सकते हैं, जबकि डेस्कटॉप अपनी बाइंडिंग्स बनाए रखता है। परिपक्व टूल्स जैसे AutoKey यही तरीका अपनाते हैं, और यह अतिरिक्त लिस्नर्स को सह-अस्तित्व की अनुमति देता है।
नीचे के उदाहरण में python-xlib और XRecord का उपयोग करके Super+V के साथ यह भी पता लगाया जाता है कि कौन-सा Super दबा था (लेफ़्ट या राइट)। यह KeyPress और KeyRelease रिपोर्ट करता है और तब भी काम करता रहता है जब Super_L मेनू को असाइन हो या Super+V AutoKey में किसी फ़ंक्शन से बंधा हो। यह इनमें से किसी क्रिया को ब्लॉक नहीं करता, क्योंकि XRecord ग्रैब नहीं करता—सिर्फ़ प्रतिबिंब देता है।
from Xlib import X, XK, display
from Xlib.ext import record
from Xlib.protocol import rq
# दो कनेक्शन खोलें: एक लोकल लुकअप्स के लिए, एक रिकॉर्डर के लिए
x_disp = display.Display()
x_rec = display.Display()
# लक्षित कुंजियाँ और मास्क
ks_v = XK.string_to_keysym('v')
kc_v = x_disp.keysym_to_keycode(ks_v)
mask_mod4 = X.Mod4Mask
# लेफ्ट/राइट Super की खोज
ks_super_l = XK.string_to_keysym("Super_L")
ks_super_r = XK.string_to_keysym("Super_R")
kc_super_l = x_disp.keysym_to_keycode(ks_super_l)
kc_super_r = x_disp.keysym_to_keycode(ks_super_r)
# बाइनरी ईवेंट पार्सर
evt_field = rq.EventField(None)
def on_record(reply):
    if reply.category != record.FromServer:
        return
    if reply.client_swapped:
        return
    if not reply.data:
        return
    evt, _ = evt_field.parse_binary_value(reply.data, x_disp.display, None, None)
    if evt.type == X.KeyPress:
        if evt.detail == kc_v and (evt.state & mask_mod4):
            print("Super+V pressed")
        if evt.detail == kc_super_l:
            print("Super_L pressed")
        elif evt.detail == kc_super_r:
            print("Super_R pressed")
    if evt.type == X.KeyRelease:
        if evt.detail == kc_v and (evt.state & mask_mod4):
            print("Super+V released")
        if evt.detail == kc_super_l:
            print("Super_L released")
        elif evt.detail == kc_super_r:
            print("Super_R released")
# बिना कुंजियाँ ग्रैब किए रिकॉर्ड कॉन्टेक्स्ट बनाएँ और सक्षम करें
ctx = x_rec.record_create_context(
    0,
    [record.AllClients],
    [{
        'core_requests': (0, 0),
        'core_replies': (0, 0),
        'ext_requests': (0, 0, 0, 0),
        'ext_replies': (0, 0, 0, 0),
        'delivered_events': (0, 0),
        'device_events': (X.KeyPress, X.KeyRelease),
        'errors': (0, 0),
        'client_started': False,
        'client_died': False,
    }]
)
print("Listening for Super+V without grabbing...")
x_rec.record_enable_context(ctx, on_record)
x_rec.record_free_context(ctx)
यह Linux Mint 22.1 (Xia) पर Mate 1.26.2 और Python 3.13 के साथ सत्यापित किया गया।
एक महत्वपूर्ण नुक्ता: सुनना ब्लॉक नहीं करता
XRecord तरीका ईवेंट्स का प्रतिबिंब देता है; उन्हें रद्द नहीं करता। यदि कोई टेक्स्ट फ़ील्ड फोकस में है, तो सिस्टम “v” फिर भी पहुँचा देगा, और आपकी प्रक्रिया को उसी Super+V का मिरर दिखेगा। यही डिज़ाइन है और डेस्कटॉप की अपनी बाइंडिंग्स के साथ सह-अस्तित्व के लक्ष्य से मेल खाता है। यदि आपको एक्सक्लूसिव हैंडलिंग चाहिए, तो ग्रैब-आधारित रास्ता अपनाना पड़ेगा—जो उसी ग्रैब के मालिक से टकराएगा।
यह क्यों मायने रखता है
Linux डेस्कटॉप पर ग्लोबल कीबोर्ड इंटीग्रेशन नीति के दायरे में रहता है: डेस्कटॉप एनवायरनमेंट कुछ कुंजियों का दावा करता है। ग्रैब-आधारित API और मिरर-आधारित लिस्निंग के फर्क को समझना समय बचाता है और नाज़ुक वर्कअराउंड्स से बचाता है। यह भी स्पष्ट करता है कि कुछ शॉर्टकट तुरंत क्यों चलते हैं जबकि Super-आधारित नहीं, और मेनू की Super बाइंडिंग को निष्क्रिय/पुनःअसाइन करने से व्यवहार क्यों बदलता है।
समापन
यदि Super+V पहले से एनवायरनमेंट ने ले रखा है, तो ग्रैब के लिए लड़ाई न करें। XRecord से निष्क्रिय रूप से सुनें और डेस्कटॉप की प्रतिक्रिया बनाए रखें। यदि आपकी ज़रूरत पहली ही दबाहट पर Super के साथ सक्रिय होना है, तो एनवायरनमेंट को इस तरह कॉन्फ़िगर करें कि वही कॉर्ड ग्रैब न करे या शॉर्टकट को डेस्कटॉप स्तर पर परिभाषित करें। AutoKey जैसे टूल दिखाते हैं कि XRecord का मिररिंग Super-मॉडिफ़ाइड कुंजियों का अवलोकन करने के लिए व्यावहारिक और मज़बूत है—बिना सिस्टम में दखल दिए।
यह लेख StackOverflow पर प्रश्न (लेखक: AlxPav Chr) और furas के उत्तर पर आधारित है।