क्या क्लिपबोर्ड के स्रोत (एप्लिकेशन) को जानना संभव है?


10

मैंने देखा है कि कभी-कभी क्लिपबोर्ड सामग्री अनुपलब्ध हो जाती है यदि स्रोत एप्लिकेशन (जहां सामग्री की प्रतिलिपि बनाई गई थी) बंद है।

यह मुझे आश्चर्यचकित करता है कि क्या यह जानना संभव है कि स्रोत एप्लिकेशन क्या है (उदाहरण के लिए शायद पीआईडी)।

क्यों? यदि स्रोत एप्लिकेशन एक टर्मिनल है, तो मैं किसी फ़ाइल के पूर्ण पथ का निर्माण करने के लिए प्रतिलिपि की गई सामग्री के सापेक्ष होने की स्थिति में, टर्मिनल की कार्यशील निर्देशिका खोजना चाहूंगा।

FYI करें, मैं वर्तमान में क्लिपबोर्ड सामग्री निर्धारित करने के लिए xclip का उपयोग कर रहा हूं, उदा

xclip -selection primary -t STRING -o 2> /dev/null

2
XGetSelectionOwner(3)आपको चयन के स्वामी की विंडो आईडी मिलती है। जिस से आप विंडो ट्री को वॉक करने की कोशिश कर सकते हैं और उदाहरण के लिए _NET_WM_PID प्रॉपर्टी के साथ एक विंडो ढूंढ सकते हैं xprop(यह मानते हुए कि विंडो उस प्रॉपर्टी को सेट करने वाले लोकल क्लाइंट से आती है)। xwininfo -root -tree | less +/0x<that-id>आवेदन की पहचान करने के लिए पर्याप्त हो सकता है।
स्टीफन चेज़लस

2
@ StéphaneChazelas ने क्या कहा। लेकिन ध्यान रखें कि आपको X11 से बाहर अन्य क्लाइंट का विश्वसनीय पीआईडी ​​मिलने की संभावना नहीं है। याद रखें कि एक्स क्लाइंट जेनेरिक नेटवर्क कनेक्शन (यूनिक्स सॉकेट या टीसीपी सॉकेट) के माध्यम से एक्स सर्वर से जुड़ते हैं, एक पीआईडी ​​अर्थहीन हो सकता है क्योंकि आवेदन स्थानीय नहीं हो सकता है। यह TCP (इन दिनों सामान्य नहीं) या SSH-अग्रेषित X11 कनेक्शन (अधिक सामान्य) से जुड़ा हो सकता है।
सेलडा

नोट के लिए धन्यवाद - मुझे लगता है कि मुझे XGetSelectionOwner का उपयोग करने के लिए कुछ सी कोड लिखने की आवश्यकता होगी? मैं शायद ऐसा कर सकता हूं - जब मैं किसी समाधान पर पहुंचूंगा तो पोस्ट करूंगा।
जेफ वार्ड

जवाबों:


5

मैंने एक उपकरण लिखा था, जो सादे अनुप्रयोग नाम (जैसे 'टर्मिनल', 'जीडिट' या 'स्मार्टगिट', जिन्हें मैंने परीक्षण किया है) को लौटाता है। ज्यादातर कोड बेशर्मी से यहां @Harvey से चुराए गए हैं

// gcc clipboard-owner.c -lX11 -o clipboard-owner

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>

#define MAX_PROPERTY_VALUE_LEN 4096

typedef unsigned long ulong;

static char *get_property(Display *, Window, Atom , const char *, ulong *);

int main(void)
{
  // Open the Display
  Display *display = XOpenDisplay(NULL);

  // Get the selection window
  Window selection_owner = XGetSelectionOwner(display, XA_PRIMARY);

  if(!selection_owner) {
    exit(0);
  } else {
      char *window_name = get_property(display, selection_owner, XA_STRING, "WM_NAME", NULL);
      printf("%s\n", window_name);
  }

  XCloseDisplay(display);
}

static char *get_property (Display *disp, Window win,
        Atom xa_prop_type, const char *prop_name, ulong *size) {
    Atom xa_prop_name;
    Atom xa_ret_type;
    int ret_format;
    ulong ret_nitems;
    ulong ret_bytes_after;
    ulong tmp_size;
    unsigned char *ret_prop;
    char *ret;

    xa_prop_name = XInternAtom(disp, prop_name, False);

    if (XGetWindowProperty(disp, win, xa_prop_name, 0,
            MAX_PROPERTY_VALUE_LEN / 4, False,
            xa_prop_type, &xa_ret_type, &ret_format,     
            &ret_nitems, &ret_bytes_after, &ret_prop) != Success) {
        printf("Cannot get %s property.\n", prop_name);
        return NULL;
    }

    if (xa_ret_type != xa_prop_type) {
        printf("Invalid type of %s property.\n", prop_name);
        XFree(ret_prop);
        return NULL;
    }

    /* null terminate the result to make string handling easier */
    tmp_size = (ret_format / 8) * ret_nitems;
    /* Correct 64 Architecture implementation of 32 bit data */
    if(ret_format==32) tmp_size *= sizeof(long)/4;
    ret = (char *)malloc(tmp_size + 1);
    memcpy(ret, ret_prop, tmp_size);
    ret[tmp_size] = '\0';

    if (size) {
        *size = tmp_size;
    }

    XFree(ret_prop);
    return ret;
}

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

मैंने "कोशिश माता-पिता को जोड़ने जब तक WM_NAME संपत्ति नहीं मिली है" को जोड़ने की कोशिश की - और यह emacs काम करता है, हालांकि रोबोमोंगो नहीं। दिलचस्प। इस उत्तर में PID खोजने के लिए कुछ प्रासंगिक जानकारी भी है: unix.stackexchange.com/questions/5478/… दिलचस्प रूप से यह PID (कार्डिनल?) सभी "टर्मिनल" खिड़कियों के लिए समान है। यह मेरे विशिष्ट उपयोग के मामले में अच्छी तरह से नहीं है, क्योंकि प्रत्येक टर्मिनल एक अलग वर्तमान कार्य निर्देशिका में हो सकता है।
जेफ वार्ड

हाँ। मुझे पीआईडी ​​पाने के लिए "_NET_WM_PID" संपत्ति के साथ कोई भाग्य नहीं था, लेकिन मुझे आशा है कि आप नाम को शुरुआती बिंदु के रूप में उपयोग कर सकते हैं।
jschlichtholz

1
@JeWWard कुछ आधुनिक टर्मिनल प्रोग्राम जैसे gnome-terminalप्रति सत्र केवल एक बार आवेदन शुरू करने के बजाय प्रति टर्मिनल विंडो प्रति एक उदाहरण के बजाय उदाहरण के लिए प्रारंभ करें xterm। शायद यही कारण है कि आप उन सभी में एक ही पीआईडी ​​देख रहे हैं? के लिए gnome-terminalआप उस मिसफिट को --disable-factoryएक विकल्प के लिए (विषम नाम) के साथ अक्षम करने में सक्षम थे, लेकिन जाहिर है कि अब संभव नहीं हो सकता है । वैसे भी, लगता है जैसे आपको टर्मिनल के अंदर चल रही प्रक्रियाओं में से एक की pwd की जरूरत है, खुद की नहीं।
सेलदा

@ कैलाडा - सही है, और यह समझ में आता है - एक्स विंडो सिस्टम खिड़कियों के बारे में जानता है, जरूरी नहीं कि प्रत्येक कार्यक्रम उनके साथ क्या करना चाहता है। यह भी प्रतीत होता है कि क्लिपबोर्ड के लिए क्रोम की एक अलग विंडो (या प्रक्रिया?) है। जाहिरा तौर पर कई स्कीमाटा हैं, और मेरा विचार पैन नहीं हो सकता है।
जेफ वार्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.