diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..cd60ae9 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,24 @@ +name: Compile example + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + + - name: Compile + run: make -C examples/mousebuttons-c/ + shell: bash diff --git a/README.md b/README.md index a7fec71..8277429 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,22 @@ Code is distributed under MIT license, feel free to use it in your proprietary p - Source split by system - Platform-agnostic structure for audio - Mouse: Left, Right, Middle, Scrollup/down +- Added: fenster_sync +- Changed: array on modkeys, mouse pos -### Mouse buttons -Inside fenster object: ```C - int mclick[5]; // left, right, middle, scroll up, scroll down (cleared after loop) - int mhold[3]; // left, right, middle (persistent until release) - //0 = false, 1 = true +struct fenster { + const char *title; + const int width; + const int height; + uint32_t *buf; + int keys[256]; // keys are mostly ASCII, but arrows are 17..20 + int modkeys[4]; // ctrl, shift, alt, meta + int mpos[2]; // mouse x, y + int mclick[5]; // left, right, middle, scroll up, scroll down (refreshed after loop) + int mhold[3]; // left, right, middle (persistent until button release) + int64_t lastsync; // last sync time +}; + +FENSTER_API void fenster_sync(struct fenster *f, int fps); ``` diff --git a/examples/mousebuttons-c/Makefile b/examples/mousebuttons-c/Makefile index b6e5121..97262f9 100644 --- a/examples/mousebuttons-c/Makefile +++ b/examples/mousebuttons-c/Makefile @@ -1,6 +1,7 @@ CFLAGS ?= -Wall -Wextra -std=c99 ifeq ($(OS),Windows_NT) + CC = gcc LDFLAGS = -lgdi32 else UNAME_S := $(shell uname -s) @@ -12,4 +13,4 @@ else endif main: main.c ../../src/fenster/fenster.h - $(CC) main.c -I../../src/fenster -o $@ $(CFLAGS) $(LDFLAGS) + $(CC) main.c -I../../src/fenster/ -o $@ $(CFLAGS) $(LDFLAGS) diff --git a/examples/mousebuttons-c/main.c b/examples/mousebuttons-c/main.c index f8591a9..e3c1e68 100644 --- a/examples/mousebuttons-c/main.c +++ b/examples/mousebuttons-c/main.c @@ -25,8 +25,9 @@ static int run() { while (fenster_loop(&f) == 0) { printf("Click: L:%d R:%d M:%d SU:%d SD:%d | \n", f.mclick[0], f.mclick[1], f.mclick[2], f.mclick[3], f.mclick[4]); + fenster_sync(&f, 60); } - + fenster_close(&f); return 0; } diff --git a/src/fenster/fenster.h b/src/fenster/fenster.h index cea3e9e..b38c067 100644 --- a/src/fenster/fenster.h +++ b/src/fenster/fenster.h @@ -16,7 +16,7 @@ #endif #include -#include +//#include #include struct fenster { @@ -24,12 +24,12 @@ struct fenster { const int width; const int height; uint32_t *buf; - int keys[256]; /* keys are mostly ASCII, but arrows are 17..20 */ - int mod; /* mod is 4 bits mask, ctrl=1, shift=2, alt=4, meta=8 */ - int x; - int y; - int mclick[5]; // left, right, middle, scroll up, scroll down (cleared after read) - int mhold[3]; // left, right, middle (persistent until release) + int keys[256]; // keys are mostly ASCII, but arrows are 17..20 + int modkeys[4]; // ctrl, shift, alt, meta + int mpos[2]; // mouse x, y + int mclick[5]; // left, right, middle, scroll up, scroll down (cleared after read) + int mhold[3]; // left, right, middle (persistent until release) + int64_t lastsync; // last sync time #if defined(__APPLE__) id wnd; #elif defined(_WIN32) @@ -51,6 +51,7 @@ 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); +FENSTER_API void fenster_sync(struct fenster *f, int fps); #define fenster_pixel(f, x, y) ((f)->buf[((y) * (f)->width) + (x)]) diff --git a/src/fenster/fenster_linux.h b/src/fenster/fenster_linux.h index e34a626..434a3c6 100644 --- a/src/fenster/fenster_linux.h +++ b/src/fenster/fenster_linux.h @@ -48,7 +48,8 @@ FENSTER_API int fenster_loop(struct fenster *f) { } break; case MotionNotify: - f->x = ev.xmotion.x, f->y = ev.xmotion.y; + f->mpos[0] = ev.xmotion.x; + f->mpos[1] = ev.xmotion.y; break; case KeyPress: case KeyRelease: { @@ -60,8 +61,10 @@ FENSTER_API int fenster_loop(struct fenster *f) { break; } } - f->mod = (!!(m & ControlMask)) | (!!(m & ShiftMask) << 1) | - (!!(m & Mod1Mask) << 2) | (!!(m & Mod4Mask) << 3); + f->modkeys[0] = !!(m & ControlMask); + f->modkeys[1] = !!(m & ShiftMask); + f->modkeys[2] = !!(m & Mod1Mask); + f->modkeys[3] = !!(m & Mod4Mask); } break; } } @@ -81,4 +84,13 @@ FENSTER_API int64_t fenster_time(void) { return time.tv_sec * 1000 + (time.tv_nsec / 1000000); } +FENSTER_API void fenster_sync(struct fenster *f, int fps) { + int64_t frame_time = 1000 / fps; + int64_t elapsed = fenster_time() - f->lastsync; + if (elapsed < frame_time) { + fenster_sleep(frame_time - elapsed); + } + + f->lastsync = fenster_time(); +} #endif /* FENSTER_LINUX_H */ diff --git a/src/fenster/fenster_mac.h b/src/fenster/fenster_mac.h index 114460e..bd1e529 100644 --- a/src/fenster/fenster_mac.h +++ b/src/fenster/fenster_mac.h @@ -117,8 +117,8 @@ FENSTER_API int fenster_loop(struct fenster *f) { case 5: case 6: { /* NSEventTypeMouseMoved */ CGPoint xy = msg(CGPoint, ev, "locationInWindow"); - f->x = (int)xy.x; - f->y = (int)(f->height - xy.y); + f->mpos[0] = (int)xy.x; + f->mpos[1] = (int)(f->height - xy.y); return 0; } case 10: /*NSEventTypeKeyDown*/ @@ -126,7 +126,10 @@ FENSTER_API int fenster_loop(struct fenster *f) { NSUInteger k = msg(NSUInteger, ev, "keyCode"); f->keys[k < 127 ? FENSTER_KEYCODES[k] : 0] = evtype == 10; NSUInteger mod = msg(NSUInteger, ev, "modifierFlags") >> 17; - f->mod = (mod & 0xc) | ((mod & 1) << 1) | ((mod >> 1) & 1); + f->modkeys[0] = (mod & 1) ? 1 : 0; // Shift + f->modkeys[1] = (mod & 2) ? 1 : 0; // Control + f->modkeys[2] = (mod & 4) ? 1 : 0; // Alt/Option + f->modkeys[3] = (mod & 8) ? 1 : 0; // Command return 0; } } @@ -147,4 +150,13 @@ FENSTER_API int64_t fenster_time(void) { return time.tv_sec * 1000 + (time.tv_nsec / 1000000); } +FENSTER_API void fenster_sync(struct fenster *f, int fps) { + int64_t frame_time = 1000 / fps; + int64_t elapsed = fenster_time() - f->lastsync; + if (elapsed < frame_time) { + fenster_sleep(frame_time - elapsed); + } + + f->lastsync = fenster_time(); +} #endif /* FENSTER_MAC_H */ diff --git a/src/fenster/fenster_windows.h b/src/fenster/fenster_windows.h index c0bf928..176570f 100644 --- a/src/fenster/fenster_windows.h +++ b/src/fenster/fenster_windows.h @@ -61,14 +61,14 @@ static LRESULT CALLBACK fenster_wndproc(HWND hwnd, UINT msg, WPARAM wParam, } break; case WM_MOUSEMOVE: - f->y = HIWORD(lParam), f->x = LOWORD(lParam); + f->mpos[1] = HIWORD(lParam), f->mpos[0] = LOWORD(lParam); break; case WM_KEYDOWN: case WM_KEYUP: { - f->mod = ((GetKeyState(VK_CONTROL) & 0x8000) >> 15) | - ((GetKeyState(VK_SHIFT) & 0x8000) >> 14) | - ((GetKeyState(VK_MENU) & 0x8000) >> 13) | - (((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000) >> 12); + f->modkeys[0] = (GetKeyState(VK_CONTROL) & 0x8000) ? 1 : 0; + f->modkeys[1] = (GetKeyState(VK_SHIFT) & 0x8000) ? 1 : 0; + f->modkeys[2] = (GetKeyState(VK_MENU) & 0x8000) ? 1 : 0; + f->modkeys[3] = ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000) ? 1 : 0; f->keys[FENSTER_KEYCODES[HIWORD(lParam) & 0x1ff]] = !((lParam >> 31) & 1); } break; case WM_DESTROY: @@ -125,4 +125,13 @@ FENSTER_API int64_t fenster_time() { return (int64_t)(count.QuadPart * 1000.0 / freq.QuadPart); } +FENSTER_API void fenster_sync(struct fenster *f, int fps) { + int64_t frame_time = 1000 / fps; + int64_t elapsed = fenster_time() - f->lastsync; + if (elapsed < frame_time) { + fenster_sleep(frame_time - elapsed); + } + + f->lastsync = fenster_time(); +} #endif /* FENSTER_WINDOWS_H */