X11 控制窗口
窗口信息查询
检索窗口信息工具 xprop
xprop执行后会出现一个光标,这个光标可以获取到窗口信息
X11 获取窗口信息,操作窗口
X11 遍历获取当前显示窗口的标题 _NET_WM_NAME, 置顶模拟键盘输入操作
开发依赖
apt install libX11-dev libXtst-dev
头文件
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysysm.h>
#include <X11/extensions/XTest.h>
编译关联
g++ -o main main.cpp -lX11 -lXtst
1.获取当前的显示和根窗口
Display* display = XOpenDisplay(NULL);
if (display == NULL) {
std::cerr << "Unable to open display" << std::endl;
return -1;
}
Window root = XDefaultRootWindow(display);
PrintAllWindows(display, root);
XCloseDisplay(display);
2.遍历当前窗口所有的子窗口
void PrintAllWindows(Display* display, Window root) {
Window parent;
Window* children;
unsigned int num_children;
char* windowName;
if (XQueryTree(display, root, &root, &parent, &children, &num_children)) {
for (unsigned int i = 0; i < num_children; i++) {
PrintWindowInfo(display, children[i]);
PrintAllWindows(display, children[i]);
}
if (children) {
XFree(children);
}
}
}
3.窗口信息查看
void PrintWindowInfo(Display* display, Window window) {
Atom ca = XInternAtom(display, "_NET_WM_NAME", False);
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char* prop_return = NULL;
if (XGetWindowProperty(display, window, ca, 0, (~0L), False, AnyPropertyType,
&actual_type, &actual_format, &nitems, &bytes_after, &prop_return) == Success) {
std::string value;
value.assign((char*)prop_return, nitems);
std::cout << "atom:" << XGetAtomName(display, ca) << std::endl;
std::cout << "Value:" << value << std::endl;
std::cout << "window:" << window << std::endl;
}
}
}
4.窗口置顶
void ActivateWindow(Display* display, Window window) {
XEvent event = { 0 };
event.xclient.type = ClientMessage;
event.xclient.message_type = XInternAtom(display, "_NET_ACTIVE_WINDOW", False);
event.xclient.display = display;
event.xclient.window = window;
event.xclient.format = 32;
event.xclient.data.l[0] = 2;
event.xclient.data.l[1] = CurrentTime;
event.xclient.data.l[2] = 0;
event.xclient.data.l[3] = 0;
event.xclient.data.l[4] = 0;
Window root = XDefaultRootWindow(display);
XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &event);
}
5.模拟键盘按键
unsigned int keycode = XKeysymToKeyCode(display, XK_Page_Down);
XTestFakeKeyEvent(display, keycode, True, 0);
XTestFakeKeyEvent(display, keycode, False, 0);
X11 屏幕抓取转为png base64输出
依赖安装
apt install libpng-dev libX11-dev
编译
g++ -o screen ScreenCap.cpp base64.cpp -lpng -lX11
#include <iostream>
#include <vector>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <png.h>
#include <base64/base64.h>
void userWriteData(png_structp png_ptr, png_bytep data, png_size_t length) {
std::vector<uint8_t>* p = (std::vector<uint8_t>*) png_get_io_ptr(png_ptr);
p->insert(p->end(), data, data + length);
}
int main() {
Display* display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
XWindowAttributes gwa;
XGetWindowAttributes(display, root, &gwa);
int width = gwa.width;
int height = gwa.height;
XImage* image = XGetImage(display, root, 0, 0, width, height, AllPlanes, ZPixmap);
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info = png_create_info_struct(png);
setjmp(png_jmpbuf(png));
std::vector<uint8_t> buffer;
png_set_write_fn(png, &buffer, userWriteData, NULL);
png_set_IHDR(
png,
info,
width, height,
8,
PNG_COLOR_TYPE_RGBA,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT
);
png_write_info(png, info);
png_bytep row = (png_bytep) malloc(4 * width * sizeof(png_byte));
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
uint32_t pixel = XGetPixel(image, x, y);
row[x*4] = (pixel >> 16) & 0xFF;
row[x*4 + 1] = (pixel >> 8) & 0xFF;
row[x*4 + 2] = pixel & 0xFF;
row[x*4 + 3] = 0xFF;
}
png_write_row(png, row);
}
png_write_end(png, NULL);
png_destroy_write_struct(&png, &info);
free(row);
XFree(image);
XCloseDisplay(display);
std::string b64_data = base64_encode(buffer.data(), buffer.size(), false);
std::cout << b64_data << std::endl;
return 0;
}