#include"node.h" #include #include #include #include #include #include #include #include #include #include #include"img.h" #include"linearity.h" #include"minitrace.h" static Display *d; static Window root; static int find_window(Display *d, Window *w, const char *contains) { if(contains) { int found = 0; Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1); Atom actualType; int format; unsigned long numItems, bytesAfter; Window *list; XTextProperty windowName; int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list); if(status >= Success) { for(int i = 0; i < numItems; i++) { status = XGetWMName(d, list[i], &windowName); if(status >= Success) { if(windowName.value && strstr((const char*) windowName.value, contains)) { *w = list[i]; found = 1; break; } } } } XFree(list); return found; } else { *w = root; return 1; } } typedef struct { CHiPubNode pub; Window xcache; XImage *ximg; XShmSegmentInfo shminfo; CHiImage *vcache; } CHiWindowNode; static int window_perform(CHiPubNode *n) { CHiWindowNode *w = (CHiWindowNode*) n; MTR_BEGIN("CHi", "window_perform"); Window toshoot; if(!find_window(d, &toshoot, CHi_Crawl(&n->sinks[0])->data.text)) return 0; size_t stride; if(!w->xcache || w->xcache != toshoot) { w->xcache = toshoot; XWindowAttributes attrs; XGetWindowAttributes(d, toshoot, &attrs); w->ximg = XShmCreateImage(d, attrs.visual, 32, ZPixmap, NULL, &w->shminfo, attrs.width, attrs.height); stride = ((w->ximg->bytes_per_line + 15) & ~15); w->shminfo.shmid = shmget(IPC_PRIVATE, stride * w->ximg->height, IPC_CREAT | 0777); w->shminfo.shmaddr = w->ximg->data = (char*) shmat(w->shminfo.shmid, 0, 0); w->shminfo.readOnly = False; XShmAttach(d, &w->shminfo); w->vcache = CHi_Image_New(2, 4, (8 * attrs.width + 15) & ~15, attrs.width, attrs.height, NULL); } else { stride = ((w->ximg->bytes_per_line + 15) & ~15); } XWindowAttributes toshootattrs; XGetWindowAttributes(d, w->xcache, &toshootattrs); XShmGetImage(d, w->xcache, w->ximg, 0, 0, AllPlanes); bool ignoreAlpha = CHi_Crawl(&w->pub.sinks[1])->data.vec4[0] != 0; // Turn u8 image to u16 #pragma omp parallel for for(size_t y = 0; y < w->vcache->height; y++) { for(size_t x = 0; x < w->vcache->width; x += 2) { __m128i c = _mm_loadu_si128((__m128i*) ((uintptr_t) w->ximg->data + y * w->ximg->bytes_per_line + x * 4)); c = _mm_shuffle_epi8(c, _mm_set_epi8(7, -128, 6, -128, 5, -128, 4, -128, 3, -128, 2, -128, 1, -128, 0, -128)); if(ignoreAlpha) { c = _mm_or_si128(c, _mm_set_epi16(0xFFFF, 0, 0, 0, 0xFFFF, 0, 0, 0)); } c = apply_gamma_epi16(c, _mm_set_ps(1, 2.2f, 2.2f, 2.2f)); _mm_storeu_si128((__m128i*) ((uintptr_t) w->vcache->data16 + y * w->vcache->stride + x * 8), c); } } n->sources[0].type = CUTIHI_VAL_SAMPLE; n->sources[0].data.sample = w->vcache; MTR_END("CHi", "window_perform"); return 1; } static void window_destroy(CHiPubNode *pubn) { CHiWindowNode *n = (CHiWindowNode*) pubn; if(n->vcache) { XShmDetach(d, &n->shminfo); shmdt(n->shminfo.shmaddr); XDestroyImage(n->ximg); } free(pubn); } CUTIVIS CHiPubNode *CHi_Window() { if(!d) { d = XOpenDisplay(NULL); root = RootWindow(d, DefaultScreen(d)); } CHiWindowNode *n = (CHiWindowNode*) calloc(1, sizeof(*n)); n->pub.type = CUTIHI_T('CWin','dow '); n->pub.Start = n->pub.Stop = NULL; n->pub.Perform = window_perform; n->pub.Destroy = window_destroy; n->pub.sinkCount = 1; n->pub.sinks = (CHiValue*) calloc(sizeof(*n->pub.sinks), 2); n->pub.sourceCount = 1; n->pub.sources = (CHiValue*) calloc(sizeof(*n->pub.sources), 1); n->xcache = 0; n->vcache = NULL; return &n->pub; } // All of the following are ews struct WindowListDatum { Window handle; char name[128]; }; CUTIVIS size_t CHi_Window_GetList(void **buf) { int found = 0; Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1); Atom actualType; int format; unsigned long numItems, bytesAfter; Window *list; XTextProperty windowName; int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list); if(status >= Success) { WindowListDatum *data = (WindowListDatum*) calloc(numItems, sizeof(*data)); size_t successfulWindows = 0; for(size_t i = 0; i < numItems; i++) { status = XGetWMName(d, list[i], &windowName); if(status >= Success) { data[successfulWindows].handle = list[i]; strncpy(data[successfulWindows].name, (char*) windowName.value, sizeof(data[successfulWindows].name)); successfulWindows++; } } XFree(list); *buf = data; return successfulWindows; } *buf = nullptr; return 0; } CUTIVIS const char *CHi_Window_GetName(void *buf, size_t i) { return ((WindowListDatum*) buf)[i].name; } CUTIVIS size_t CHi_Window_GetHandle(void *buf, size_t i) { return ((WindowListDatum*) buf)[i].handle; } CUTIVIS void CHi_Window_FreeList(void *buf) { free(buf); }