클립 보드의 소스 (애플리케이션)를 아는 것이 가능합니까?


10

소스 응용 프로그램 (컨텐츠가 복사 된 위치)을 닫으면 클립 보드 내용을 사용할 수없는 경우가 있습니다.

이것은 소스 어플리케이션이 무엇인지 (예를 들어 PID에 의해) 알 수 있는지 궁금하게 만듭니다.

왜? 소스 응용 프로그램이 터미널 인 경우 복사 된 내용이 상대 경로 인 경우 파일의 전체 경로를 구성하기 위해 터미널의 작업 디렉토리를 찾고 싶습니다.

참고로, 현재 클립 보드 내용을 결정하기 위해 xclip을 사용하고 있습니다.

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

2
XGetSelectionOwner(3)선택 소유자의 창 ID를 가져옵니다. 여기에서 창 트리를 걸어 _NET_WM_PID 속성을 가진 창을 찾아보십시오 xprop(해당 창은 해당 속성을 설정하는 로컬 클라이언트에서 온 것으로 가정). xwininfo -root -tree | less +/0x<that-id>응용 프로그램을 식별하기에 충분할 수 있습니다.
Stéphane Chazelas 2016 년

2
@ StéphaneChazelas가 말한 것. 그러나 X11에서 다른 클라이언트의 신뢰할 수있는 PID를 얻을 수는 없습니다. X 클라이언트는 일반 네트워크 연결 (UNIX 소켓 또는 TCP 소켓)을 통해 X 서버에 연결한다는 것을 기억하면 PID가 응용 프로그램이 로컬이 아니기 때문에 의미가 없을 수 있습니다. TCP (요즘 더 이상 사용되지 않음) 또는 SSH 전달 X11 연결 (보다 일반적)을 통해 연결되었을 수 있습니다.
Celada

메모 주셔서 감사합니다-XGetSelectionOwner에 액세스하려면 C 코드를 작성해야한다고 가정합니까? 아마 그렇게 할 수 있습니다-해결책에 도달하면 다시 게시 할 것입니다.
Jeff Ward

답변:


5

나는 평범한 응용 프로그램 이름 (예 : 테스트 한 것들 인 'Terminal', 'gedit'또는 'SmartGit')을 반환하는 도구를 작성했습니다. 대부분의 코드는 @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;
}

좋은 시작 감사합니다! 흠, 그것은 터미널, 파이어 폭스 및 크롬과 함께 작동하지만 emacs 및 robomongo 등과 같은 다른 사람들에게는 "WM_NAME 속성을 얻을 수 없습니다"를 던집니다.
Jeff Ward

나는 추가 시도 아니지만 robomongo하고 만든 이맥스 작업이 - "WM_NAME 속성이 발견 될 때까지 시도 부모"을 수행합니다. 흥미 롭군 이 답변에는 PID 찾기에 대한 관련 정보도 있습니다. unix.stackexchange.com/questions/5478/… 흥미롭게도이 PID (추기경)는 모든 "터미널"창에서 동일합니다. 각 터미널이 별도의 현재 작업 디렉토리에있을 수 있기 때문에 특정 유스 케이스에는 적합하지 않습니다.
Jeff Ward

예. PID를 얻기 위해 "_NET_WM_PID"속성을 사용하여 운이 없었지만 이름을 시작점으로 사용할 수 있기를 바랍니다.
jschlichtholz 2016 년

1
@JeffWard 일부 최신 터미널 프로그램은 gnome-terminal예를 들어, 터미널 창당 하나의 인스턴스가 아닌 세션 당 응용 프로그램 인스턴스를 한 번만 시작합니다 xterm. 아마도 이것이 모든 PID에서 동일한 PID를 보는 이유일까요? 예 gnome-terminal를 들어 --disable-factory(옵션의 이상한 이름)으로 그 기능을 비활성화 할 수 있었지만 더 이상 가능하지 않을 것 입니다. 어쨌든, 터미널 자체가 아닌 터미널 내부에서 실행되는 프로세스 중 하나의 암호가 필요하다고 들립니다.
Celada 2016 년

@Celada-그렇습니다. X 윈도우 시스템은 각 프로그램이 윈도우와 관련하여 선택하는 것이 아니라 윈도우에 대해 알고 있습니다. Chrome에는 클립 보드 전용의 별도의 창 (또는 프로세스?)이있는 것으로 보입니다. 분명히 많은 스키마가 있으며 내 아이디어가 사라지지 않을 수 있습니다.
Jeff Ward
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.