//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <iostream>
#include <list>
#include <stdlib.h>
#include <QProcess>
#include <QWindow>
using namespace std;
#ifdef WIN32
#include <windows.h>
WId Pid2Wid(quint64 procID, const char *lpszClassName)
{
char szBuf[256];
HWND hWnd = GetTopWindow(GetDesktopWindow());
while (hWnd)
{
DWORD wndProcID = 0;
GetWindowThreadProcessId(hWnd, &wndProcID);
if (wndProcID == procID)
{
GetClassName(hWnd, szBuf, sizeof(szBuf));
if (strcmp(szBuf, lpszClassName) == 0)
{
return (WId)hWnd;
}
}
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
}
return 0;
}
#else
#include <X11/Xlib.h>
#include <X11/Xatom.h>
class WindowsMatchingPid
{
public:
WindowsMatchingPid(Display *display, Window wRoot, unsigned long pid)
: _display(display)
, _pid(pid)
{
// Get the PID property atom.
_atomPID = XInternAtom(display, "_NET_WM_PID", True);
if (_atomPID == None)
{
cout << "No such atom" << endl;
return;
}
search(wRoot);
}
inline const list<Window> &result() const { return _result; }
private:
unsigned long _pid;
Atom _atomPID;
Display *_display;
list<Window> _result;
private:
void search(Window w)
{
// Get the PID for the current 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)
{
// If the PID matches, add this window to the result set.
if (_pid == *((unsigned long *)propPID))
_result.push_back(w);
XFree(propPID);
}
}
// Recurse into child windows.
Window wRoot;
Window wParent;
Window *wChild;
unsigned nChildren;
if (0 != XQueryTree(_display, w, &wRoot, &wParent, &wChild, &nChildren))
{
for (unsigned i = 0; i < nChildren; i++)
search(wChild[i]);
}
}
};
int Pid2Wid(int nPid)
{
// Start with the root window.
char *pDsp = getenv("DISPLAY");
Display *display = XOpenDisplay(pDsp);
if (display == NULL)
{
return 0;
}
WindowsMatchingPid match(display, XDefaultRootWindow(display), nPid);
const list<Window> &result = match.result();
if (result.size())
{
return (unsigned long)(*result.begin());
}
else
{
return 0;
}
}
#endif
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget), m_Layout(this)
{
ui->setupUi(this);
m_Layout.addWidget(ui->pushButton);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
QProcess *pProc = new QProcess(this);
pProc->setProcessChannelMode(QProcess::ForwardedErrorChannel);
#ifdef WIN32
pProc->start("Notepad");
pProc->waitForFinished(1000);
WId wid = Pid2Wid(pProc->processId(), "Notepad");
#else
pProc->start("xterm");// X11自带的xterm、xclock可以正确地被嵌入启动,xedit等能够被启动,不能得到窗口ID,故不能被正确嵌入。Qt编写的程序应该均能被正确嵌入。
pProc->waitForFinished(1000);
WId wid = Pid2Wid(pProc->processId());
#endif
QWindow *pWin = QWindow::fromWinId(wid);
printf("%d\t%p\t%d\n", (int)pProc->processId(), pWin, (int)wid);
if (pWin != NULL)
{
QWidget *pWid = QWidget::createWindowContainer(pWin, this);
m_Layout.addWidget(pWid);
m_Layout.update();
}
}