cuticle/hi/relay_win.c
mid 3993163d6d Start Windows compatibility
screen_capture_lite turned out to be pretty broken and so I brought back
my old X11 implementation for the Window node, for Unices only.
Hopefully SCL actually works on Windows because lemme tell you, I do not
want to go knee-deep in that.

Additionally, SAIL was replaced with stb_image because I couldn't get
SAIL to build under MinGW.
2025-10-12 11:23:49 +03:00

150 lines
3.9 KiB
C

#include"relay.h"
#include"img.h"
#include<tmmintrin.h>
#include<stdio.h>
#include<pthread.h>
#include<stdatomic.h>
#include<math.h>
#include<windows.h>
#include<winuser.h>
#include<pthread.h>
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;
}
typedef struct {
CHiPubNode pub;
pthread_t thrd;
char key[64];
atomic_bool on;
atomic_bool active;
} CHiKeyhookNode;
static _Thread_local CHiKeyhookNode *lookwhatyoumademedo;
static LRESULT CALLBACK keyhook_handler(int nCode, WPARAM wParam, LPARAM lParam) {
bool eatKeystroke = false;
CHiKeyhookNode *n = lookwhatyoumademedo;
if(nCode == HC_ACTION) {
switch(wParam) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP: {
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
bool press = wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN;
char keyname[64];
GetKeyNameTextA(p->vkCode, keyname, sizeof(keyname));
if(!strcmp(keyname, n->key)) {
n->on = press;
}
break;
}
}
}
return eatKeystroke ? true : CallNextHookEx(NULL, nCode, wParam, lParam);
}
static void *keyhook_thread(void *ud) {
CHiKeyhookNode *n = ud;
lookwhatyoumademedo = n;
HHOOK hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, keyhook_handler, 0, 0);
MSG msg;
while(n->active && !GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hhkLowLevelKybd);
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;
n->active = false;
pthread_join(n->thrd, NULL);
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';
n->active = true;
pthread_create(&n->thrd, NULL, keyhook_thread, n);
return &n->pub;
}