#include"relay.h" #include"img.h" #include #include #include #include #include #include #include static int scale_perform(CHiPubNode *n) { float *scales = CHi_Crawl(&n->sinks[0])->data.vec4; CHiImage *img = CHi_Crawl(&n->sinks[1])->data.sample; if(n->sources[0].data.sample) { CHi_Image_Free(n->sources[0].data.sample); } CHiImage *ret = n->sources[0].data.sample = CHi_Image_New(img->bpc, img->channels, img->stride, img->width, img->height, NULL); __m128i iscales = _mm_set_epi16( scales[3] * 65535, scales[0] * 65535, scales[1] * 65535, scales[2] * 65535, scales[3] * 65535, scales[0] * 65535, scales[1] * 65535, scales[2] * 65535 ); for(size_t y = 0; y < img->height; y++) { for(size_t x = 0; x < img->width; x += 16) { __m128i pixels8 = _mm_loadu_si128((__m128i*) ((uintptr_t) img->data16 + y * img->stride + x)); __m128i mulled = _mm_mulhi_epu16(pixels8, iscales); _mm_storeu_si128((__m128i*) ((uintptr_t) ret->data16 + y * img->stride + x), mulled); } } return 1; } CUTIVIS CHiPubNode *CHi_ComponentScale() { CHiPubNode *n = calloc(1, sizeof(*n)); n->type = CUTIHI_T('CCmp','nScl'); n->Start = n->Stop = NULL; n->Perform = scale_perform; n->sinkCount = 2; n->sinks = calloc(sizeof(*n->sinks), n->sinkCount); n->sourceCount = 1; n->sources = calloc(sizeof(*n->sources), n->sourceCount); return n; } static Display *dpy; static XkbDescPtr xKeyboardDesc; typedef struct { CHiPubNode pub; XRecordContext rc; pthread_t thrd; char key[64]; atomic_bool on; } CHiKeyhookNode; static void keyhook_handler(XPointer ud, XRecordInterceptData *recdata) { if(recdata->category != XRecordFromServer) { return; } int type = ((unsigned char*) recdata->data)[0] & 0x7F; int key = ((unsigned char*) recdata->data)[1]; int repeat = recdata->data[2] & 1; CHiKeyhookNode *n = (CHiKeyhookNode*) ud; char keyname[XkbKeyNameLength + 1] = {}; memcpy(keyname, xKeyboardDesc->names->keys[key].name, XkbKeyNameLength); if(!repeat && !strcmp(keyname, n->key)) { if(type == KeyPress) { n->on = 1; } else if(type == KeyRelease) { n->on = 0; } } XRecordFreeData(recdata); } static void *keyhook_thread(void *ud) { CHiKeyhookNode *n = ud; XRecordRange *rr = XRecordAllocRange(); rr->device_events.first = KeyPress; rr->device_events.last = ButtonRelease; n->rc = XRecordCreateContext(dpy, 0, &(XRecordClientSpec) {XRecordAllClients}, 1, &rr, 1); XRecordEnableContext(dpy, n->rc, keyhook_handler, (XPointer) n); return NULL; } static int keyhook_perform(CHiPubNode *n) { CHiKeyhookNode *me = (CHiKeyhookNode*) n; strncpy(me->key, CHi_Crawl(&n->sinks[0])->data.text, 63); me->key[63] = '\0'; n->sources[0].type = CUTIHI_VAL_VEC4; if(n->ng->compilationStatus == CUTIHI_COMP_READY || n->sinks[1].data.vec4[0] == 0) { n->sources[0].data.vec4[0] = ((CHiKeyhookNode*) n)->on; } else if(((CHiKeyhookNode*) n)->on) { n->sources[0].data.vec4[0] = fminf(1, n->sources[0].data.vec4[0] + CHi_Time_GetDelta(n->ng) * n->sinks[1].data.vec4[0]); } else { n->sources[0].data.vec4[0] = fmaxf(0, n->sources[0].data.vec4[0] - CHi_Time_GetDelta(n->ng) * n->sinks[1].data.vec4[0]); } return 1; } static void keyhook_destroy(CHiPubNode *pubn) { CHiKeyhookNode *n = (void*) pubn; XRecordDisableContext(dpy, n->rc); XRecordFreeContext(dpy, n->rc); free(n); } CUTIVIS CHiPubNode *CHi_Keyhook() { CHiKeyhookNode *n = calloc(1, sizeof(*n)); n->pub.type = CUTIHI_T('CKey','hook'); n->pub.Start = n->pub.Stop = NULL; n->pub.Perform = keyhook_perform; n->pub.Destroy = keyhook_destroy; n->pub.sinkCount = 2; n->pub.sinks = calloc(sizeof(*n->pub.sinks), n->pub.sinkCount); n->pub.sourceCount = 1; n->pub.sources = calloc(sizeof(*n->pub.sources), n->pub.sourceCount); n->on = 0; n->key[0] = '\n'; if(!dpy) { dpy = XOpenDisplay(NULL); xKeyboardDesc = XkbGetMap(dpy, 0, XkbUseCoreKbd); XkbGetNames(dpy, XkbKeyNamesMask, xKeyboardDesc); } pthread_create(&n->thrd, NULL, keyhook_thread, n); return &n->pub; }