How to get an X11 Window from a Process ID?

后端 未结 8 743
孤街浪徒
孤街浪徒 2020-11-27 11:30

Under Linux, my C++ application is using fork() and execv() to launch multiple instances of OpenOffice so as to view some powerpoint slide shows. This part works.

Ne

8条回答
  •  情话喂你
    2020-11-27 12:23

    I took the freedom to re-implement the OP's code using some modern C++ features. It maintains the same functionalities but I think that it reads a bit better. Also it does not leak even if the vector insertion happens to throw.

    // Attempt to identify a window by name or attribute.
    // originally written by Adam Pierce 
    // revised by Dario Pellegrini 
    
    #include 
    #include 
    #include 
    #include 
    
    
    std::vector pid2windows(pid_t pid, Display* display, Window w) {
      struct implementation {
        struct FreeWrapRAII {
          void * data;
          FreeWrapRAII(void * data): data(data) {}
          ~FreeWrapRAII(){ XFree(data); }
        };
    
        std::vector result;
        pid_t pid;
        Display* display;
        Atom atomPID;
    
        implementation(pid_t pid, Display* display): pid(pid), display(display) {
          // Get the PID property atom
          atomPID = XInternAtom(display, "_NET_WM_PID", True);
          if(atomPID == None) {
            throw std::runtime_error("pid2windows: no such atom");
          }
        }
    
        std::vector getChildren(Window w) {
          Window    wRoot;
          Window    wParent;
          Window   *wChild;
          unsigned  nChildren;
          std::vector children;
          if(0 != XQueryTree(display, w, &wRoot, &wParent, &wChild, &nChildren)) {
            FreeWrapRAII tmp( wChild );
            children.insert(children.end(), wChild, wChild+nChildren);
          }
          return children;
        }
    
        void emplaceIfMatches(Window w) {
          // Get the PID for the given Window
          Atom           type;
          int            format;
          unsigned long  nItems;
          unsigned long  bytesAfter;
          unsigned char *propPID = 0;
          if(Success == XGetWindowProperty(display, w, atomPID, 0, 1, False, XA_CARDINAL,
                                           &type, &format, &nItems, &bytesAfter, &propPID)) {
            if(propPID != 0) {
              FreeWrapRAII tmp( propPID );
              if(pid == *reinterpret_cast(propPID)) {
                result.emplace_back(w);
              }
            }
          }
        }
    
        void recurse( Window w) {
          emplaceIfMatches(w);
          for (auto & child: getChildren(w)) {
            recurse(child);
          }
        }
    
        std::vector operator()( Window w ) {
          result.clear();
          recurse(w);
          return result;
        }
      };
      //back to pid2windows function
      return implementation{pid, display}(w);
    }
    
    std::vector pid2windows(const size_t pid, Display* display) {
      return pid2windows(pid, display, XDefaultRootWindow(display));
    }
    
    
    int main(int argc, char **argv) {
      if(argc < 2)
        return 1;
    
      int pid = atoi(argv[1]);
      std::cout << "Searching for windows associated with PID " << pid << std::endl;
    
      // Start with the root window.
      Display *display = XOpenDisplay(0);
      auto res = pid2windows(pid, display);
    
      // Print the result.
      for( auto & w: res) {
        std::cout << "Window #" << static_cast(w) << std::endl;
      }
    
      XCloseDisplay(display);
      return 0;
    }
    

提交回复
热议问题