Apakah mungkin mengetahui sumber (aplikasi) clipboard?

10

Saya perhatikan bahwa terkadang konten clipboard menjadi tidak tersedia jika aplikasi sumber (tempat konten itu disalin) ditutup.

Ini membuat saya bertanya-tanya apakah mungkin untuk mengetahui apa aplikasi sumber itu (misalnya, mungkin dengan PID).

Mengapa? Jika aplikasi sumber adalah terminal, saya ingin mencari direktori kerja terminal, jika konten yang disalin adalah jalur relatif, untuk membuat jalur lengkap ke file.

FYI, saya saat ini menggunakan xclip untuk menentukan konten clipboard, mis

xclip -selection primary -t STRING -o 2> /dev/null
Jeff Ward
sumber
2
XGetSelectionOwner(3)memberi Anda id jendela pemilik pilihan. Dari mana Anda dapat berjalan di pohon jendela untuk mencoba dan menemukan jendela dengan properti _NET_WM_PID misalnya xprop( dengan asumsi jendela tersebut berasal dari klien lokal yang menetapkan properti itu). xwininfo -root -tree | less +/0x<that-id>mungkin cukup untuk mengidentifikasi aplikasi.
Stéphane Chazelas
2
Apa yang dikatakan @StéphaneChazelas. Namun perlu diketahui bahwa Anda tidak mungkin mendapatkan PID yang dapat diandalkan dari klien lain dari X11. Mengingat bahwa klien X terhubung ke server X melalui koneksi jaringan umum (soket UNIX atau soket TCP), PID mungkin tidak ada artinya karena aplikasi mungkin tidak bersifat lokal. Mungkin terhubung melalui TCP (tidak umum lagi hari ini) atau koneksi X11 SSH-diteruskan (lebih umum).
Celada
Terima kasih atas catatannya - saya berasumsi saya harus menulis beberapa kode C untuk mengakses XGetSelectionOwner? Saya mungkin bisa melakukan itu - saya akan memposting kembali ketika saya mendapatkan solusi.
Jeff Ward

Jawaban:

5

Saya menulis alat yang mengembalikan nama aplikasi biasa (misalnya 'Terminal', 'gedit' atau 'SmartGit' yang merupakan yang saya uji). Sebagian besar kode dicuri tanpa malu-malu dari @ Harvey di sini .

// 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;
}
jschlichtholz
sumber
Awal yang bagus, terima kasih! Hmm, ia bekerja dengan terminal, firefox, dan chrome, tetapi melempar "Tidak bisa mendapatkan properti WM_NAME" untuk orang lain seperti emacs dan robomongo, dll.
Jeff Ward
Saya mencoba menambahkan "coba induk hingga properti WM_NAME ditemukan" - dan itu membuat emacs berfungsi, meskipun bukan robomongo. Menarik. Jawaban ini juga memiliki beberapa info yang relevan untuk menemukan PID: unix.stackexchange.com/questions/5478/... Menariknya PID ini (menjadi kardinal?) Adalah sama untuk semua jendela "Terminal". Ini bukan pertanda baik untuk kasus penggunaan khusus saya, karena setiap terminal mungkin berada dalam direktori kerja saat ini yang terpisah.
Jeff Ward
Iya. Saya tidak beruntung dengan properti "_NET_WM_PID" untuk mendapatkan PID tapi saya berharap Anda bisa menggunakan nama itu sebagai titik awal.
jschlichtholz
1
@JeffWard beberapa program terminal modern seperti gnome-terminalmulai hanya sekali instance aplikasi per sesi, bukan satu instance per jendela terminal seperti terhormat xterm. Mungkin itu sebabnya Anda melihat PID yang sama di semuanya? Untuk gnome-terminalAnda dulu dapat menonaktifkan misfeature dengan --disable-factory(nama ganjil untuk opsi) tetapi tampaknya itu tidak mungkin lagi . Ngomong-ngomong, sepertinya Anda perlu pwd dari salah satu proses yang berjalan di dalam terminal, bukan dari dirinya sendiri.
Celada
@Celada - benar, dan masuk akal - sistem X window tahu tentang windows, belum tentu apa yang masing-masing program pilih untuk lakukan dengan mereka. Tampaknya juga Chrome memiliki jendela terpisah (atau proses?) Yang didedikasikan untuk clipboard. Rupanya ada banyak skema, dan ide saya mungkin tidak berhasil.
Jeff Ward