クリップボードのソース(アプリケーション)を知ることは可能ですか?


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>アプリケーションを識別するには十分かもしれません。
ステファンChazelas

2
@StéphaneChazelasが言ったこと。ただし、X11から他のクライアントの信頼できるPIDを取得する可能性は低いことに注意してください。Xクライアントが汎用ネットワーク接続(UNIXソケットまたはTCPソケット)を介してXサーバーに接続することを思い出してください。アプリケーションがローカルでない可能性があるため、PIDは意味がない場合があります。TCP(最近は一般的ではありません)またはSSH転送X11接続(より一般的)を介して接続される可能性があります。
Celada、2015年

メモをありがとう-私はXGetSelectionOwnerにアクセスするためにいくつかのCコードを書く必要があると思いますか?私はおそらくそれを行うことができます-解決策が得られたらポストバックします。
ジェフワード

回答:


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;
}

ありがとうございます。うーん、ターミナル、Firefox、Chromeで動作しますが、emacsやrobomongoなどの他のユーザーに対して「WM_NAMEプロパティを取得できません」をスローします。
ジェフワード

私は、追加しようとした「WM_NAMEプロパティが見つかるまでトライ親」 -とないrobomongoけれども、Emacsは仕事行われています。面白い。この回答には、PIDを見つけるための関連情報もいくつか含まれています。unix.stackexchange.com / questions / 5478 / 興味深いことに、このPID(カーディナルか?)はすべての「ターミナル」ウィンドウで同じです。これは私の特定のユースケースにはうまくいきません。なぜなら、各ターミナルは別々の現在の作業ディレクトリにあるかもしれないからです。
Jeff Ward

はい。「_NET_WM_PID」プロパティを使用してPIDを取得することはできませんでしたが、名前を出発点として使用できることを願っています。
jschlichtholz 2015年

1
@JeffWardのようないくつかの最新のターミナルプログラムgnome-terminalは、由緒あるようなターミナルウィンドウごとに1つのインスタンスではなく、セッションごとにアプリケーションのインスタンスを1回だけ起動しますxterm。多分それがあなたがそれらすべてで同じPIDを見ている理由ですか?以下のためにgnome-terminalあなたがその設計ミスを無効にすることができるように使用される--disable-factory(オプションの奇妙な名前)が、どうやらそれはもはや可能性がないかもしれません。とにかく、それ自体ではなく、ターミナル内で実行されているプロセスの1つのパスワードが必要なように聞こえます。
Celada、2015年

@Celada-そうです、そしてそれは理にかなっています-Xウィンドウシステムはウィンドウについて知っています、必ずしも各プログラムがウィンドウで何をするかを選択するわけではありません。また、Chromeにはクリップボード専用の別のウィンドウ(またはプロセス?)があるようです。どうやらスキーマはたくさんあり、私の考えではうまくいかないかもしれません。
ジェフウォード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.