Sending Keystrokes to a X Window

2020-07-17 16:07发布

问题:

I am currently experimenting with xdotool to send keys to a process (I understand that it may not work for all processes that does not set _NET_WM_PID). I have trouble sending keystrokes to windows other from the focus. It does work if you are sending keystrokes to the CURRENTWINDOW. Below is the snippet that I used to test xdotool's functionality.

extern "C"{
  #include <xdo.h>
}
//extern "C" xdo_window_search
#include <iostream>
#include <string.h>

using namespace std;

int main(){
    xdo_t* p_xdo = xdo_new(NULL);

    // Allocate memory for search query.
    xdo_search_t s;
    // Clear the allocated memory.
    memset(&s, 0, sizeof(xdo_search_t));
    // Set the search query.
    s.pid = 1916;
    s.max_depth = -1;
    s.searchmask = SEARCH_PID;
    s.require = xdo_search::SEARCH_ANY;
    // Allocate memory for output
    Window* windows;
    int no_windows;
    xdo_window_search(p_xdo,&s,&windows,&no_windows);
    cout << no_windows << endl;
    // Prints all windows' names with matching criteria
    for( int i=0;i<no_windows;i++ ){
        unsigned char * name;
        int size;
        int type;
        xdo_get_window_name(p_xdo,windows[i],&name,&size,&type);
        cout << i << ":" << name << endl;
    }
    for( int i=0;i<no_windows;i++ ){
        xdo_type(p_xdo,windows[i],"Hello World",0);
    }
    //xdo_type(p_xdo,CURRENTWINDOW,"Hello World",0); // This does work.
    return 0;
}

In additional to testing xdotool's functionality, I've looked into xdotool's source code. Interestingly, I found that they are using Xtest to send keystrokes to the focused window (CURRENTWINDOW) and X11's XSendEvent for other windows. I turned to xdotool because I couldn't get XSendEvent to work and Xtest cannot send keys to any other windows than the focused window.

Am I not using the xdotool correctly? Does xdotool not work with all *nix OS with X11?

[I am running this on Ubuntu 13.04.]


EDIT

So, it looks like that does work but not for all windows that it finds. For example, it works for firefox but not gedit and gnome-terminal although it found gedit and gnome-terminal by its pid. It behaves differently if I used CURRENTWINDOW.

So, it would be great if someone can explain why is this so. Like, is it related the force send flag in an XEvent?

回答1:

Directly from the xdotool manual:

SENDEVENT NOTES

If you are trying to send key input to a specific window, and it does not appear to be working, then it's likely your application is ignoring the events xdotool is generating. This is fairly common.

Sending keystrokes to a specific window uses a different API than simply typing to the active window. If you specify 'xdotool type --window 12345 hello' xdotool will generate key events and send them directly to window 12345. However, X11 servers will set a special flag on all events generated in this way (see XEvent.xany.send_event in X11's manual). Many programs observe this flag and reject these events.

It is important to note that for key and mouse events, we only use XSendEvent when a specific window is targeted. Otherwise, we use XTEST.

Some programs can be configured to accept events even if they are generated by xdotool. Seek the documentation of your application for help.

Specific application notes (from the author's testing): * Firefox 3 seems to ignore all input when it does not have focus. * xterm can be configured while running with ctrl+leftclick, 'Allow SendEvents' * gnome-terminal appears to accept generated input by default.