lolautoaccept/src/screen.cpp

140 lines
3.6 KiB
C++

// g++ screena.cpp -o screena -lX11 -lXext -Ofast -mfpmath=both -march=native -m64 -funroll-loops -mavx2 `pkg-config opencv --cflags --libs` && ./screena
// This includes most headers!
#include "screen.h"
#include <X11/cursorfont.h>
#include <Log.h>
const uint32_t ScreenShot::DEFAULTWIDTH = 1280;
const uint32_t ScreenShot::DEFAULTHEIGHT = 720;
// https://stackoverflow.com/a/39781697/4399859
static void searchWindows(Display* disp, Window top, const std::string& search, std::vector<Window>& result) {
char* window_name;
if (XFetchName(disp, top, &window_name)) {
if (search == window_name) {
result.push_back(top);
return; // dont look for kids
}
}
Window* children = nullptr, dummy;
unsigned int nchildren;
if (!XQueryTree(disp, top, &dummy, &dummy, &children, &nchildren))
return;
for (unsigned int i = 0; i < nchildren; i++) {
searchWindows(disp, children[i], search, result);
}
if (children)
XFree((char*) children);
}
std::vector<ScreenShot*> ScreenShot::getWindows(const std::string& name) {
Display* display = XOpenDisplay(nullptr);
Log::info << "searching for: " << name;
std::vector<Window> list;
searchWindows(display, DefaultRootWindow(display), name, list);
std::vector<ScreenShot*> out;
out.reserve(list.size());
for (Window w : list) {
ScreenShot* ss = new ScreenShot(display, w);
if(ss->valid)
out.push_back(ss);
}
return out;
}
bool ScreenShot::updateAttrib() {
Status attrb = XGetWindowAttributes(display, window, &wattrib);
if (attrb == BadWindow || attrb == BadDrawable) {
Log::error << "XGetWindowAttributes() falied";
return false;
}
if((wattrib.c_class != InputOutput) || (wattrib.map_state != IsViewable)) {
Log::warn << "Window is not viewable - window class: " << wattrib.c_class << " map state: " << wattrib.map_state << " - ignoring window";
return false;
}
return true;
}
bool ScreenShot::initImg() {
bool upd = updateAttrib();
if(!upd) return false;
char* wname = nullptr;
XFetchName(display, window, &wname);
if (wname)
windowname = std::string(wname);
Log::info << "Window " << std::quoted(windowname) << " x: " << wattrib.x << " y: " << wattrib.y << " w: " << wattrib.width << " h: " << wattrib.height;
ximg = XShmCreateImage(display, wattrib.visual, wattrib.depth, ZPixmap, NULL, &shminfo, wattrib.width, wattrib.height);
shminfo.shmid = shmget(IPC_PRIVATE, ximg->bytes_per_line * ximg->height, IPC_CREAT | 0777);
shminfo.shmaddr = ximg->data = (char*) shmat(shminfo.shmid, 0, 0);
shminfo.readOnly = false;
if (shminfo.shmid < 0)
Log::fatal << "Fatal shminfo error!";
Status s1 = XShmAttach(display, &shminfo);
Log::info << "XShmAttach() " << (s1 ? "success!" : "failure!");
init = true;
return true;
}
ScreenShot::ScreenShot() {
display = XOpenDisplay(nullptr);
window = DefaultRootWindow(display);
int count_screens = ScreenCount(display);
if (count_screens == 0) {
puts("no screen info!");
}
for (int i = 0; i < count_screens; ++i) {
Screen* screen = ScreenOfDisplay(display, i);
printf("\tScreen %d: %dX%d\n", i + 1, screen->width, screen->height);
}
valid = initImg();
}
ScreenShot::ScreenShot(Display* d, Window w) : display(d), window(w), closeDisp(false) {
valid = initImg();
}
void ScreenShot::take(cv::Mat& cv_img) {
if (init)
init = false;
XShmGetImage(display, window, ximg, 0, 0, 0x00ffffff);
cv_img = cv::Mat(wattrib.height, wattrib.width, CV_8UC4, ximg->data);
}
void ScreenShot::operator() (cv::Mat& cv_img) {
take(cv_img);
}
ScreenShot::~ScreenShot() {
if (!init)
XDestroyImage(ximg);
XShmDetach(display, &shminfo);
shmdt(shminfo.shmaddr);
if (closeDisp)
XCloseDisplay(display);
}