diff --git a/README.md b/README.md index 8618c34..be2455b 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Compile it and run: ``` # Linux -cc main.c -lX11 -lasound -o main && ./main +cc main.c -lX11 -lXinerama -lasound -o main && ./main # macOS cc main.c -framework Cocoa -framework AudioToolbox -o main && ./main # windows diff --git a/examples/input-c/main.c b/examples/input-c/main.c index 255ce51..8c7ad15 100644 --- a/examples/input-c/main.c +++ b/examples/input-c/main.c @@ -63,6 +63,11 @@ static int run() { } } *p = '\0'; + + int left_down = (f.mouse >> MOUSE_LEFT_BUTTON) & 1; + int middle_down = (f.mouse >> MOUSE_MIDDLE_BUTTON) & 1; + int right_down = (f.mouse >> MOUSE_RIGHT_BUTTON) & 1; + fenster_rect(&f, 0, 0, W, H, 0); /* draw mouse "pointer" */ if (f.x > 5 && f.y > 5 && f.x < f.width - 5 && f.y < f.height - 5) { diff --git a/fenster.h b/fenster.h index ed4332e..b98ba50 100644 --- a/fenster.h +++ b/fenster.h @@ -1,23 +1,13 @@ #ifndef FENSTER_H #define FENSTER_H -#if defined(__APPLE__) -#include -#include -#include -#elif defined(_WIN32) -#include -#else -#define _DEFAULT_SOURCE 1 -#include -#include -#include -#include -#endif - #include #include +#define MOUSE_LEFT_BUTTON 0 +#define MOUSE_MIDDLE_BUTTON 1 +#define MOUSE_RIGHT_BUTTON 2 + struct fenster { const char *title; const int width; @@ -28,7 +18,40 @@ struct fenster { int x; int y; int mouse; + void* backend; +}; + +#ifndef FENSTER_API +#define FENSTER_API extern +#endif +#ifndef FENSTER_DLL +#define FENSTER_DLL(name,...) name(__VA_ARGS__) +#endif +FENSTER_API void FENSTER_DLL(fenster_screen_size,int *width, int *height); +FENSTER_API int FENSTER_DLL(fenster_open,struct fenster *f); +FENSTER_API int FENSTER_DLL(fenster_loop,struct fenster *f); +FENSTER_API void FENSTER_DLL(fenster_close,struct fenster *f); +FENSTER_API void FENSTER_DLL(fenster_sleep,int64_t ms); +FENSTER_API int64_t FENSTER_DLL(fenster_time,void); +#define fenster_pixel(f, x, y) ((f)->buf[((y) * (f)->width) + (x)]) + +#ifndef FENSTER_HEADER #if defined(__APPLE__) +#include +#include +#include +#elif defined(_WIN32) +#include +#else +#define _DEFAULT_SOURCE 1 +#include +#include +#include +#include +#include +#endif +typedef struct{ + #if defined(__APPLE__) id wnd; #elif defined(_WIN32) HWND hwnd; @@ -38,19 +61,8 @@ struct fenster { GC gc; XImage *img; #endif -}; - -#ifndef FENSTER_API -#define FENSTER_API extern -#endif -FENSTER_API int fenster_open(struct fenster *f); -FENSTER_API int fenster_loop(struct fenster *f); -FENSTER_API void fenster_close(struct fenster *f); -FENSTER_API void fenster_sleep(int64_t ms); -FENSTER_API int64_t fenster_time(void); -#define fenster_pixel(f, x, y) ((f)->buf[((y) * (f)->width) + (x)]) +} backend_t; -#ifndef FENSTER_HEADER #if defined(__APPLE__) #define msg(r, o, s) ((r(*)(id, SEL))objc_msgSend)(o, sel_getUid(s)) #define msg1(r, o, s, A, a) \ @@ -92,6 +104,10 @@ static BOOL fenster_should_close(id v, SEL s, id w) { return YES; } +FENSTER_API void fenster_screen_size(int *width, int *height) { + //NOT IMPLEMENTED +} + FENSTER_API int fenster_open(struct fenster *f) { msg(id, cls("NSApplication"), "sharedApplication"); msg1(void, NSApp, "setActivationPolicy:", NSInteger, 0); @@ -198,8 +214,22 @@ static LRESULT CALLBACK fenster_wndproc(HWND hwnd, UINT msg, WPARAM wParam, DestroyWindow(hwnd); break; case WM_LBUTTONDOWN: + f->mouse |= 1 << MOUSE_LEFT_BUTTON; + break; case WM_LBUTTONUP: - f->mouse = (msg == WM_LBUTTONDOWN); + f->mouse &= ~(1 << MOUSE_LEFT_BUTTON); + break; + case WM_MBUTTONDOWN: + f->mouse |= 1 << MOUSE_MIDDLE_BUTTON; + break; + case WM_MBUTTONUP: + f->mouse &= ~(1 << MOUSE_MIDDLE_BUTTON); + break; + case WM_RBUTTONDOWN: + f->mouse |= 1 << MOUSE_RIGHT_BUTTON; + break; + case WM_RBUTTONUP: + f->mouse &= ~(1 << MOUSE_RIGHT_BUTTON); break; case WM_MOUSEMOVE: f->y = HIWORD(lParam), f->x = LOWORD(lParam); @@ -221,7 +251,16 @@ static LRESULT CALLBACK fenster_wndproc(HWND hwnd, UINT msg, WPARAM wParam, return 0; } +FENSTER_API void fenster_screen_size(int *width, int *height) { + RECT desktop; + const HWND hDesktop = GetDesktopWindow(); + GetWindowRect(hDesktop, &desktop); + *width = desktop.right; + *height = desktop.bottom; +} + FENSTER_API int fenster_open(struct fenster *f) { + backend_t* b = malloc(sizeof(backend_t)); HINSTANCE hInstance = GetModuleHandle(NULL); WNDCLASSEX wc = {0}; wc.cbSize = sizeof(WNDCLASSEX); @@ -230,21 +269,25 @@ FENSTER_API int fenster_open(struct fenster *f) { wc.hInstance = hInstance; wc.lpszClassName = f->title; RegisterClassEx(&wc); - f->hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, f->title, f->title, + b->hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, f->title, f->title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, f->width, f->height, NULL, NULL, hInstance, NULL); - if (f->hwnd == NULL) + if (b->hwnd == NULL) return -1; - SetWindowLongPtr(f->hwnd, GWLP_USERDATA, (LONG_PTR)f); - ShowWindow(f->hwnd, SW_NORMAL); - UpdateWindow(f->hwnd); + SetWindowLongPtr(b->hwnd, GWLP_USERDATA, (LONG_PTR)f); + ShowWindow(b->hwnd, SW_NORMAL); + UpdateWindow(b->hwnd); + f->backend = b; return 0; } -FENSTER_API void fenster_close(struct fenster *f) { (void)f; } +FENSTER_API void fenster_close(struct fenster *f) { + free(f->backend); +} FENSTER_API int fenster_loop(struct fenster *f) { + backend_t* b = (backend_t*)f->backend; MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) @@ -252,41 +295,70 @@ FENSTER_API int fenster_loop(struct fenster *f) { TranslateMessage(&msg); DispatchMessage(&msg); } - InvalidateRect(f->hwnd, NULL, TRUE); + InvalidateRect(b->hwnd, NULL, TRUE); return 0; } #else // clang-format off static int FENSTER_KEYCODES[124] = {XK_BackSpace,8,XK_Delete,127,XK_Down,18,XK_End,5,XK_Escape,27,XK_Home,2,XK_Insert,26,XK_Left,20,XK_Page_Down,4,XK_Page_Up,3,XK_Return,10,XK_Right,19,XK_Tab,9,XK_Up,17,XK_apostrophe,39,XK_backslash,92,XK_bracketleft,91,XK_bracketright,93,XK_comma,44,XK_equal,61,XK_grave,96,XK_minus,45,XK_period,46,XK_semicolon,59,XK_slash,47,XK_space,32,XK_a,65,XK_b,66,XK_c,67,XK_d,68,XK_e,69,XK_f,70,XK_g,71,XK_h,72,XK_i,73,XK_j,74,XK_k,75,XK_l,76,XK_m,77,XK_n,78,XK_o,79,XK_p,80,XK_q,81,XK_r,82,XK_s,83,XK_t,84,XK_u,85,XK_v,86,XK_w,87,XK_x,88,XK_y,89,XK_z,90,XK_0,48,XK_1,49,XK_2,50,XK_3,51,XK_4,52,XK_5,53,XK_6,54,XK_7,55,XK_8,56,XK_9,57}; // clang-format on +FENSTER_API void fenster_screen_size(int *width, int *height){ + Display *display = XOpenDisplay(NULL); + + if (XineramaIsActive(display)) { + int screen_count; + XineramaScreenInfo *screens = XineramaQueryScreens(display, &screen_count); + if(screens){ + *width = screens[0].width; + *height = screens[0].height; + XFree(screens); + } + + } + else { + Screen *screen = XScreenOfDisplay(display,0); + *width = WidthOfScreen(screen); + *height = HeightOfScreen(screen); + } + + XCloseDisplay(display); +} FENSTER_API int fenster_open(struct fenster *f) { - f->dpy = XOpenDisplay(NULL); - int screen = DefaultScreen(f->dpy); - f->w = XCreateSimpleWindow(f->dpy, RootWindow(f->dpy, screen), 0, 0, f->width, - f->height, 0, BlackPixel(f->dpy, screen), - WhitePixel(f->dpy, screen)); - f->gc = XCreateGC(f->dpy, f->w, 0, 0); - XSelectInput(f->dpy, f->w, + backend_t* b = malloc(sizeof(backend_t)); + b->dpy = XOpenDisplay(NULL); + int screen = DefaultScreen(b->dpy); + b->w = XCreateSimpleWindow(b->dpy, RootWindow(b->dpy, screen), 0, 0, f->width, + f->height, 0, BlackPixel(b->dpy, screen), + WhitePixel(b->dpy, screen)); + b->gc = XCreateGC(b->dpy, b->w, 0, 0); + XSelectInput(b->dpy, b->w, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask); - XStoreName(f->dpy, f->w, f->title); - XMapWindow(f->dpy, f->w); - XSync(f->dpy, f->w); - f->img = XCreateImage(f->dpy, DefaultVisual(f->dpy, 0), 24, ZPixmap, 0, + XStoreName(b->dpy, b->w, f->title); + XMapWindow(b->dpy, b->w); + XSync(b->dpy, b->w); + b->img = XCreateImage(b->dpy, DefaultVisual(b->dpy, 0), 24, ZPixmap, 0, (char *)f->buf, f->width, f->height, 32, 0); + f->backend = b; return 0; } -FENSTER_API void fenster_close(struct fenster *f) { XCloseDisplay(f->dpy); } +FENSTER_API void fenster_close(struct fenster *f) { + XCloseDisplay(((backend_t*)f->backend)->dpy); + free(f->backend); +} FENSTER_API int fenster_loop(struct fenster *f) { + backend_t* b = f->backend; XEvent ev; - XPutImage(f->dpy, f->w, f->gc, f->img, 0, 0, 0, 0, f->width, f->height); - XFlush(f->dpy); - while (XPending(f->dpy)) { - XNextEvent(f->dpy, &ev); + XPutImage(b->dpy, b->w, b->gc, b->img, 0, 0, 0, 0, f->width, f->height); + XFlush(b->dpy); + while (XPending(b->dpy)) { + XNextEvent(b->dpy, &ev); switch (ev.type) { case ButtonPress: + f->mouse |= 1 << (ev.xbutton.button -1); + break; case ButtonRelease: - f->mouse = (ev.type == ButtonPress); + f->mouse &= ~(1 << (ev.xbutton.button -1)); break; case MotionNotify: f->x = ev.xmotion.x, f->y = ev.xmotion.y; @@ -294,7 +366,7 @@ FENSTER_API int fenster_loop(struct fenster *f) { case KeyPress: case KeyRelease: { int m = ev.xkey.state; - int k = XkbKeycodeToKeysym(f->dpy, ev.xkey.keycode, 0, 0); + int k = XkbKeycodeToKeysym(b->dpy, ev.xkey.keycode, 0, 0); for (unsigned int i = 0; i < 124; i += 2) { if (FENSTER_KEYCODES[i] == k) { f->keys[FENSTER_KEYCODES[i + 1]] = (ev.type == KeyPress); @@ -327,7 +399,7 @@ FENSTER_API void fenster_sleep(int64_t ms) { } FENSTER_API int64_t fenster_time(void) { struct timespec time; - clock_gettime(CLOCK_REALTIME, &time); + clock_gettime(0/*CLOCK_REALTIME*/, &time); return time.tv_sec * 1000 + (time.tv_nsec / 1000000); } #endif