È possibile conoscere la fonte (applicazione) degli appunti?


10

Ho notato che a volte il contenuto degli appunti non è disponibile se l'applicazione di origine (da cui è stato copiato il contenuto) è chiusa.

Questo mi porta a chiedermi se è possibile sapere qual è l'applicazione di origine (ad esempio, forse tramite PID).

Perché? Se l'applicazione di origine è un terminale, vorrei trovare la directory di lavoro del terminale, nel caso in cui il contenuto copiato sia un percorso relativo, per costruire un percorso completo di un file.

Cordiali saluti, attualmente sto usando xclip per determinare il contenuto degli appunti, ad es

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

2
XGetSelectionOwner(3)ti dà l'ID della finestra del proprietario della selezione. Da cui è possibile percorrere l'albero delle finestre per provare a trovare una finestra con una proprietà _NET_WM_PID, ad esempio con xprop(supponendo che la finestra provenga da un client locale che imposta quella proprietà). xwininfo -root -tree | less +/0x<that-id>potrebbe essere sufficiente per identificare l'applicazione.
Stéphane Chazelas,

2
Cosa ha detto @ StéphaneChazelas. Ma tieni presente che è improbabile che tu ottenga un PID affidabile dell'altro client da X11. Ricordando che i client X si connettono ai server X tramite connessioni di rete generiche (socket UNIX o socket TCP), un PID potrebbe non avere senso poiché l'applicazione potrebbe non essere locale. Potrebbe essere collegato tramite TCP (non più comune in questi giorni) o una connessione X11 inoltrata da SSH (più comune).
Celada,

Grazie per le note - Presumo che dovrò scrivere del codice C per accedere a XGetSelectionOwner? Probabilmente posso farlo - ti rispondo quando arrivo a una soluzione.
Jeff Ward,

Risposte:


5

Ho scritto uno strumento che restituisce il semplice nome dell'applicazione (ad esempio "Terminale", "gedit" o "SmartGit" che sono quelli che ho testato). La maggior parte del codice viene sottratta spudoratamente da @Harvey qui .

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

Un grande inizio, grazie! Hmm, funziona con terminal, firefox e chrome, ma genera "Impossibile ottenere la proprietà WM_NAME" per altri come emacs e robomongo, ecc. Mi chiedo se questa è la parte "walk the tree" a cui si riferiva Stéphane.
Jeff Ward,

Ho provato ad aggiungere un "prova parent fino a quando non viene trovata la proprietà WM_NAME" - e questo ha fatto funzionare emacs, sebbene non robomongo. Interessante. Questa risposta ha anche alcune informazioni rilevanti per trovare il PID: unix.stackexchange.com/questions/5478/… È interessante notare che questo PID (essendo cardinale?) È lo stesso per tutte le finestre "Terminale". Questo non è di buon auspicio per il mio caso d'uso specifico, poiché ciascun terminale potrebbe trovarsi in una directory di lavoro corrente separata.
Jeff Ward,

Sì. Non ho avuto fortuna con la proprietà "_NET_WM_PID" per ottenere il PID ma speravo che tu potessi usare il nome come punto di partenza.
jschlichtholz,

1
@JeffWard alcuni moderni programmi terminali come gnome-terminalstart solo una volta l'istanza dell'applicazione per sessione anziché un'istanza per finestra terminale come venerabile xterm. Forse è per questo che stai vedendo lo stesso PID in tutti loro? Perché prima gnome-terminaleri in grado di disabilitare quel malfunzionamento con --disable-factory(nome dispari per un'opzione) ma apparentemente ciò potrebbe non essere più possibile . Ad ogni modo, sembra che tu abbia bisogno della pwd di uno dei processi in esecuzione all'interno del terminale, non di se stesso.
Celada,

@Celada - giusto, e ha senso - il sistema X Window conosce Windows, non necessariamente ciò che ogni programma sceglie di fare con loro. Sembra anche che Chrome abbia una finestra (o processo?) Separata dedicata agli appunti. Apparentemente ci sono molti schemi e la mia idea potrebbe non andare a buon fine.
Jeff Ward,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.