summaryrefslogtreecommitdiff
path: root/src/konwinlib.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/konwinlib.h')
-rw-r--r--src/konwinlib.h1357
1 files changed, 0 insertions, 1357 deletions
diff --git a/src/konwinlib.h b/src/konwinlib.h
deleted file mode 100644
index c50f828..0000000
--- a/src/konwinlib.h
+++ /dev/null
@@ -1,1357 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * konwinlib.h
- *
- * Copyright (c) 2026 KonAki
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef KONWINLIB_H
-#define KONWINLIB_H
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/*** definitions ***/
-
-typedef struct kon_context kon_context_t;
-
-bool kon_init(void);
-void kon_deinit(void);
-
-typedef struct kon_window kon_window_t;
-
-typedef enum kon_windowFlags {
- KON_WINDOW_NONE = 0,
- KON_WINDOW_TRANSPARENT = 1 << 0,
- KON_WINDOW_NO_DECOR = 1 << 1,
- KON_WINDOW_ALWAYS_ONTOP = 1 << 2,
- KON_WINDOW_CENTER = 1 << 3,
- KON_WINDOW_RESIZABLE = 1 << 4
-} kon_windowFlags_t;
-
-typedef enum kon_eventType {
- KON_EVENT_NONE = 0,
- KON_EVENT_CLOSE,
- KON_EVENT_RESIZE,
- KON_EVENT_KEY_DOWN,
- KON_EVENT_KEY_UP,
- KON_EVENT_MOUSE_DOWN,
- KON_EVENT_MOUSE_UP,
- KON_EVENT_MOUSE_MOVE
-} kon_eventType_t;
-
-typedef enum kon_mouseButton {
- KON_MOUSE_LEFT = 0,
- KON_MOUSE_MIDDLE,
- KON_MOUSE_RIGHT
-} kon_mouseButton_t;
-
-typedef enum kon_key {
- KON_KEY_UNKNOWN = 0,
-
- KON_KEY_A, KON_KEY_B, KON_KEY_C, KON_KEY_D, KON_KEY_E, KON_KEY_F, KON_KEY_G,
- KON_KEY_H, KON_KEY_I, KON_KEY_J, KON_KEY_K, KON_KEY_L, KON_KEY_M, KON_KEY_N, KON_KEY_O, KON_KEY_P,
- KON_KEY_Q, KON_KEY_R, KON_KEY_S, KON_KEY_T, KON_KEY_U, KON_KEY_V,
- KON_KEY_W, KON_KEY_X, KON_KEY_Y, KON_KEY_Z,
-
- KON_KEY_0, KON_KEY_1, KON_KEY_2, KON_KEY_3, KON_KEY_4, KON_KEY_5, KON_KEY_6, KON_KEY_7, KON_KEY_8, KON_KEY_9,
-
- KON_KEY_F1, KON_KEY_F2, KON_KEY_F3, KON_KEY_F4, KON_KEY_F5, KON_KEY_F6,
- KON_KEY_F7, KON_KEY_F8, KON_KEY_F9, KON_KEY_F10, KON_KEY_F11, KON_KEY_F12,
-
- KON_KEY_LEFT, KON_KEY_RIGHT, KON_KEY_UP, KON_KEY_DOWN,
-
- KON_KEY_SPACE, KON_KEY_ENTER, KON_KEY_TAB, KON_KEY_BACKSPACE,
- KON_KEY_ESCAPE, KON_KEY_DELETE,
-
- KON_KEY_LEFT_SHIFT, KON_KEY_RIGHT_SHIFT,
- KON_KEY_LEFT_CTRL, KON_KEY_RIGHT_CTRL,
- KON_KEY_LEFT_ALT, KON_KEY_RIGHT_ALT,
-
- KON_KEY_MINUS, KON_KEY_EQUAL,
- KON_KEY_LEFT_BRACKET, KON_KEY_RIGHT_BRACKET,
- KON_KEY_SEMICOLON, KON_KEY_APOSTROPHE,
- KON_KEY_COMMA, KON_KEY_PERIOD, KON_KEY_SLASH, KON_KEY_BACKSLASH,
- KON_KEY_GRAVE,
-
- KON_KEY_COUNT
-} kon_key_t;
-
-typedef struct kon_event {
- kon_eventType_t type;
- int width, height; /* will be used to store data for resize events */
- int key;
- int mouseX, mouseY;
- kon_mouseButton_t mouseButton;
-} kon_event_t;
-
-kon_window_t *kon_createWindow(const char *title, int x, int y, int width, int height, kon_windowFlags_t flags);
-void kon_destroyWindow(kon_window_t *window);
-
-bool kon_windowShouldClose(kon_window_t *window);
-
-void kon_setExitKey(kon_window_t *window, int key);
-
-void kon_setWindowPos(kon_window_t *window, int x, int y);
-void kon_setWindowSize(kon_window_t *window, int width, int height);
-
-void kon_getWindowPos(kon_window_t *window, int *x, int *y);
-void kon_getWindowSize(kon_window_t *window, int *width, int *height);
-
-int kon_pollEvent(kon_window_t *window, kon_event_t *event);
-void kon_blitPixels(kon_window_t *window, const uint32_t *pixels, int width, int height);
-
-// added these for web dev
-typedef void (*kon_mainLoopFn)(void *userData);
-void kon_runMainLoop(kon_window_t *window, kon_mainLoopFn callback, void *userData);
-
-/*** implementation ***/
-
-#ifdef KONWINLIB_IMPLEMENTATION
-
-static kon_context_t *kon_ctx;
-
-#define KON_EVENT_QUEUE_SIZE 256
-
-typedef struct kon_eventQueue {
- kon_event_t events[KON_EVENT_QUEUE_SIZE];
- int head, count;
-} kon_eventQueue_t;
-
-static void kon_pushEvent_(kon_eventQueue_t *q, const kon_event_t *event) {
- /* only the newest mouse move or resize matters, so overwrite instead of piling up */
- if (q->count > 0 && (event->type == KON_EVENT_MOUSE_MOVE || event->type == KON_EVENT_RESIZE)) {
- kon_event_t *last = &q->events[(q->head + q->count - 1) % KON_EVENT_QUEUE_SIZE];
- if (last->type == event->type) {
- *last = *event;
- return;
- }
- }
-
- if (q->count == KON_EVENT_QUEUE_SIZE) return;
- q->events[(q->head + q->count) % KON_EVENT_QUEUE_SIZE] = *event;
- q->count++;
-}
-
-static bool kon_popEvent_(kon_eventQueue_t *q, kon_event_t *event) {
- if (q->count == 0) return false;
- *event = q->events[q->head];
- q->head = (q->head + 1) % KON_EVENT_QUEUE_SIZE;
- q->count--;
- return true;
-}
-
-#ifdef __EMSCRIPTEN__
-
-#include <emscripten/emscripten.h>
-#include <emscripten/html5.h>
-#include <string.h>
-
-struct kon_context {
- int initialized;
-};
-
-struct kon_window {
- char canvasID[64];
- bool shouldClose;
- int exitKey;
-
- bool hasKeyEvent;
- kon_eventType_t keyEventType;
- int keyEventKey;
-
- bool hasResizeEvent;
- int resizeWidth, resizeHeight;
-
- bool hasMouseEvent;
- kon_eventType_t mouseEventType;
- int mouseEventX, mouseEventY;
- kon_mouseButton_t mouseEventButton;
-};
-
-static kon_key_t kon_translateEmKey_(int keyCode) {
- switch (keyCode) {
- case 65: return KON_KEY_A;
- case 66: return KON_KEY_B;
- case 67: return KON_KEY_C;
- case 68: return KON_KEY_D;
- case 69: return KON_KEY_E;
- case 70: return KON_KEY_F;
- case 71: return KON_KEY_G;
- case 72: return KON_KEY_H;
- case 73: return KON_KEY_I;
- case 74: return KON_KEY_J;
- case 75: return KON_KEY_K;
- case 76: return KON_KEY_L;
- case 77: return KON_KEY_M;
- case 78: return KON_KEY_N;
- case 79: return KON_KEY_O;
- case 80: return KON_KEY_P;
- case 81: return KON_KEY_Q;
- case 82: return KON_KEY_R;
- case 83: return KON_KEY_S;
- case 84: return KON_KEY_T;
- case 85: return KON_KEY_U;
- case 86: return KON_KEY_V;
- case 87: return KON_KEY_W;
- case 88: return KON_KEY_X;
- case 89: return KON_KEY_Y;
- case 90: return KON_KEY_Z;
-
- case 48: return KON_KEY_0;
- case 49: return KON_KEY_1;
- case 50: return KON_KEY_2;
- case 51: return KON_KEY_3;
- case 52: return KON_KEY_4;
- case 53: return KON_KEY_5;
- case 54: return KON_KEY_6;
- case 55: return KON_KEY_7;
- case 56: return KON_KEY_8;
- case 57: return KON_KEY_9;
-
- case 112: return KON_KEY_F1;
- case 113: return KON_KEY_F2;
- case 114: return KON_KEY_F3;
- case 115: return KON_KEY_F4;
- case 116: return KON_KEY_F5;
- case 117: return KON_KEY_F6;
- case 118: return KON_KEY_F7;
- case 119: return KON_KEY_F8;
- case 120: return KON_KEY_F9;
- case 121: return KON_KEY_F10;
- case 122: return KON_KEY_F11;
- case 123: return KON_KEY_F12;
-
- case 37: return KON_KEY_LEFT;
- case 39: return KON_KEY_RIGHT;
- case 38: return KON_KEY_UP;
- case 40: return KON_KEY_DOWN;
-
- case 32: return KON_KEY_SPACE;
- case 13: return KON_KEY_ENTER;
- case 9: return KON_KEY_TAB;
- case 8: return KON_KEY_BACKSPACE;
- case 27: return KON_KEY_ESCAPE;
- case 46: return KON_KEY_DELETE;
-
- case 16: return KON_KEY_LEFT_SHIFT;
- case 17: return KON_KEY_LEFT_CTRL;
- case 18: return KON_KEY_LEFT_ALT;
-
- case 189: return KON_KEY_MINUS;
- case 187: return KON_KEY_EQUAL;
- case 219: return KON_KEY_LEFT_BRACKET;
- case 221: return KON_KEY_RIGHT_BRACKET;
- case 186: return KON_KEY_SEMICOLON;
- case 222: return KON_KEY_APOSTROPHE;
- case 188: return KON_KEY_COMMA;
- case 190: return KON_KEY_PERIOD;
- case 191: return KON_KEY_SLASH;
- case 220: return KON_KEY_BACKSLASH;
- case 192: return KON_KEY_GRAVE;
-
- default: return KON_KEY_UNKNOWN;
- }
-}
-bool kon_init(void) {
- kon_context_t *ctx = malloc(sizeof(kon_context_t));
- if (!ctx) return false;
-
- ctx->initialized = 1;
- kon_ctx = ctx;
- return true;
-}
-
-void kon_deinit(void) {
- if (!kon_ctx) return;
-
- free(kon_ctx);
- kon_ctx = NULL;
-}
-
-static EM_BOOL kon_keyDownCallback_(int eventType, const EmscriptenKeyboardEvent *e, void *userData) {
- (void)eventType;
- kon_window_t *window = (kon_window_t *)userData;
-
- window->hasKeyEvent = true;
- window->keyEventType = KON_EVENT_KEY_DOWN;
- window->keyEventKey = kon_translateEmKey_(e->keyCode);
-
- if (window->exitKey != 0 && window->keyEventKey == window->exitKey) {
- window->shouldClose = true;
- }
-
- return EM_TRUE;
-}
-
-static EM_BOOL kon_keyUpCallback_(int eventType, const EmscriptenKeyboardEvent *e, void *userData) {
- (void)eventType;
- kon_window_t *window = (kon_window_t *)userData;
-
- window->hasKeyEvent = true;
- window->keyEventType = KON_EVENT_KEY_UP;
- window->keyEventKey = kon_translateEmKey_(e->keyCode);
-
- return EM_TRUE;
-}
-
-static EM_BOOL kon_mouseDownCallback_(int eventType, const EmscriptenMouseEvent *e, void *userData) {
- (void)eventType;
- kon_window_t *window = (kon_window_t *)userData;
-
- if (e->button > KON_MOUSE_RIGHT) return EM_FALSE;
-
- window->hasMouseEvent = true;
- window->mouseEventType = KON_EVENT_MOUSE_DOWN;
- window->mouseEventButton = (kon_windowButton_t)e->button;
- window->mouseEventX = e->targetX;
- window->mouseEventY = e->targetY;
-
- return EM_TRUE;
-}
-
-static EM_BOOL kon_mouseUpCallback_(int eventType, const EmscriptenMouseEvent *e, void *userData) {
- (void)eventType;
- kon_window_t *window = (kon_window_t *)userData;
-
- if (e->button > KON_MOUSE_RIGHT) return EM_FALSE:
-
- window->hasMouseEvent = true;
- window->mouseEventType = KON_EVENT_MOUSE_UP;
- window->mouseEventButton = (kon_windowButton_t)e->button;
- window->mouseEventX = e->targetX;
- window->mouseEventY = e->targetY;
-
- return EM_TRUE;
-}
-
-static EM_BOOL kon_mouseMoveCallback_(int eventType, const EmscriptenMouseEvent *e, void *userData) {
- (void)eventType;
- kon_window_t *window = (kon_window_t *)userData;
-
- window->hasMouseEvent = true;
- window->mouseEventType = KON_EVENT_MOUSE_MOVE;
- window->mouseEventX = e->targetX;
- window->mouseEventY = e->targetY;
-
- return EM_TRUE;
-}
-
-kon_window_t *kon_createWindow(const char *title, int x, int y, int width, int height, kon_windowFlags_t flags) {
- (void)x; (void)y; (void)flags;
-
- if (!kon_ctx) {
- fprintf(stderr, "kon_createWindow: error creating window, no ctx\n");
- return NULL;
- }
-
- kon_window_t *window = malloc(sizeof(kon_window_t));
- if (!window) return NULL;
-
- strncpy(window->canvasID, "#canvas", sizeof(window->canvasID) - 1);
- window->canvasID[sizeof(window->canvasID) - 1] = '\0';
-
- window->shouldClose = false;
- window->exitKey = 0;
- window->hasKeyEvent = false;
- window->hasResizeEvent = false;
- window->hasMouseEvent = false;
-
- emscripten_set_canvas_element_size(window->canvasID, width, height);
-
- EM_ASM({
- try { document.title = UTF8ToString($0); } catch (e) {}
- }, title);
-
- emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, window, EM_FALSE, kon_keyDownCallback_);
- emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, window, EM_FALSE, kon_keyUpCallback_);
- emscripten_set_mousedown_callback(window->canvasID, window, EM_FALSE, kon_mouseDownCallback_);
- emscripten_set_mouseup_callback(window->canvasID, window, EM_FALSE, kon_mouseUpCallback_);
- emscripten_set_mousemove_callback(window->canvasID, window, EM_FALSE, kon_mouseMoveCallback_);
-
- return window;
-}
-
-void kon_destroyWindow(kon_window_t *window) {
- if (!window) return;
-
- emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, NULL);
- emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, NULL);
- emscripten_set_mousedown_callback(window->canvasID, NULL, EM_FALSE, NULL);
- emscripten_set_mouseup_callback(window->canvasID, NULL, EM_FALSE, NULL);
- emscripten_set_mousemove_callback(window->canvasID, NULL, EM_FALSE, NULL);
-
- free(window);
-}
-
-bool kon_windowShouldClose(kon_window_t *window) {
- if (!window) return true;
- return window->shouldClose;
-}
-
-void kon_setExitKey(kon_window_t *window, int key) {
- if (!window) return;
- window->exitKey = key;
-}
-
-void kon_setWindowPos(kon_window_t *window, int x, int y) {
- (void)window; (void)x; (void)y;
-}
-
-void kon_setWindowSize(kon_window_t *window, int width, int height) {
- if (!window) return;
- emscripten_set_canvas_element_size(window->canvasID, width, height);
-}
-
-void kon_getWindowPos(kon_window_t *window, int *x, int *y) {
- (void)window;
- if (x) *x = 0;
- if (y) *y = 0;
-}
-
-void kon_getWindowSize(kon_window_t *window, int *width, int *height) {
- if (!window || !width || !height) return;
-
- double w, h;
- emscripten_get_element_css_size(window->canvasID, &w, &h);
- *width = (int)w;
- *height = (int)h;
-}
-
-int kon_pollEvent(kon_window_t *window, kon_event_t *event) {
- if (!window || !event) return 0;
-
- event->type = KON_EVENT_NONE;
-
- if (window->hasResizeEvent) {
- event->type = KON_EVENT_RESIZE;
- event->width = window->resizeWidth;
- event->height = window->resizeHeight;
- window->hasResizeEvent = false;
- return 1;
- }
-
- if (window->hasKeyEvent) {
- event->type = window->keyEventType;
- event->key = window->keyEventKey;
- window->hasKeyEvent = false;
- return 1;
- }
-
- if (window->hasMouseEvent) {
- event->type = window->mouseEventType;
- event->mouseX = window->mouseEventX;
- event->mouseY = window-<mouseEventY;
- event->mouseButton = window->mouseEventButton;
- window->hasMouseEvent = false;
- return 1;
- }
-
- return 0;
-}
-
-EM_JS(void, kon_jsBlit_, (const char *canvasID, uint32_t *pixels, int width, int height), {
- var sel = UTF8ToString(canvasID);
- var canvas = document.querySelector(sel);
- if (!canvas) return;
-
- if (!canvas.__konCtx) canvas.__konCtx = canvas.getContext('2d');
- var ctx = canvas.__konCtx;
-
- if (!canvas.__konImgData || canvas.__konImgData.width !== width || canvas.__konImgData.height !== height) {
- canvas.__konImgData = ctx.createImageData(width, height);
- }
- var imgData = canvas.__konImgData;
-
- var dst = new Uint32Array(imgData.data.buffer);
- var srcIdx = pixels >> 2;
- var count = width * height;
-
- for (var i = 0; i < count; i++) {
- var px = HEAPU32[srcIdx + i];
- dst[i] = (px & 0xFF00FF00) | ((px & 0x00FF0000) >>> 16) | ((px & 0x000000FF) << 16);
- }
-
- ctx.putImageData(imgData, 0, 0);
-});
-
-void kon_blitPixels(kon_window_t *window, const uint32_t *pixels, int width, int height) {
- if (!window || !pixels) return;
- kon_jsBlit_(window->canvasID, (uint32_t *)pixels, width, height);
-}
-
-#elif defined(__linux__) || defined(__unix__)
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/extensions/Xrandr.h>
-#include <X11/keysym.h>
-#include <string.h>
-
-static kon_key_t kon_translateX11Key_(KeySym sym) {
- switch (sym) {
- case XK_a: return KON_KEY_A;
- case XK_b: return KON_KEY_B;
- case XK_c: return KON_KEY_C;
- case XK_d: return KON_KEY_D;
- case XK_e: return KON_KEY_E;
- case XK_f: return KON_KEY_F;
- case XK_g: return KON_KEY_G;
- case XK_h: return KON_KEY_H;
- case XK_i: return KON_KEY_I;
- case XK_j: return KON_KEY_J;
- case XK_k: return KON_KEY_K;
- case XK_l: return KON_KEY_L;
- case XK_m: return KON_KEY_M;
- case XK_n: return KON_KEY_N;
- case XK_o: return KON_KEY_O;
- case XK_p: return KON_KEY_P;
- case XK_q: return KON_KEY_Q;
- case XK_r: return KON_KEY_R;
- case XK_s: return KON_KEY_S;
- case XK_t: return KON_KEY_T;
- case XK_u: return KON_KEY_U;
- case XK_v: return KON_KEY_V;
- case XK_w: return KON_KEY_W;
- case XK_x: return KON_KEY_X;
- case XK_y: return KON_KEY_Y;
- case XK_z: return KON_KEY_Z;
-
- case XK_0: return KON_KEY_0;
- case XK_1: return KON_KEY_1;
- case XK_2: return KON_KEY_2;
- case XK_3: return KON_KEY_3;
- case XK_4: return KON_KEY_4;
- case XK_5: return KON_KEY_5;
- case XK_6: return KON_KEY_6;
- case XK_7: return KON_KEY_7;
- case XK_8: return KON_KEY_8;
- case XK_9: return KON_KEY_9;
-
- case XK_F1: return KON_KEY_F1;
- case XK_F2: return KON_KEY_F2;
- case XK_F3: return KON_KEY_F3;
- case XK_F4: return KON_KEY_F4;
- case XK_F5: return KON_KEY_F5;
- case XK_F6: return KON_KEY_F6;
- case XK_F7: return KON_KEY_F7;
- case XK_F8: return KON_KEY_F8;
- case XK_F9: return KON_KEY_F9;
- case XK_F10: return KON_KEY_F10;
- case XK_F11: return KON_KEY_F11;
- case XK_F12: return KON_KEY_F12;
-
- case XK_Left: return KON_KEY_LEFT;
- case XK_Right: return KON_KEY_RIGHT;
- case XK_Up: return KON_KEY_UP;
- case XK_Down: return KON_KEY_DOWN;
-
- case XK_space: return KON_KEY_SPACE;
- case XK_Return: return KON_KEY_ENTER;
- case XK_Tab: return KON_KEY_TAB;
- case XK_BackSpace: return KON_KEY_BACKSPACE;
- case XK_Escape: return KON_KEY_ESCAPE;
- case XK_Delete: return KON_KEY_DELETE;
-
- case XK_Shift_L: return KON_KEY_LEFT_SHIFT;
- case XK_Shift_R: return KON_KEY_RIGHT_SHIFT;
- case XK_Control_L: return KON_KEY_LEFT_CTRL;
- case XK_Control_R: return KON_KEY_RIGHT_CTRL;
- case XK_Alt_L: return KON_KEY_LEFT_ALT;
- case XK_Alt_R: return KON_KEY_RIGHT_ALT;
-
- case XK_minus: return KON_KEY_MINUS;
- case XK_equal: return KON_KEY_EQUAL;
- case XK_bracketleft: return KON_KEY_LEFT_BRACKET;
- case XK_bracketright: return KON_KEY_RIGHT_BRACKET;
- case XK_semicolon: return KON_KEY_SEMICOLON;
- case XK_apostrophe: return KON_KEY_APOSTROPHE;
- case XK_comma: return KON_KEY_COMMA;
- case XK_period: return KON_KEY_PERIOD;
- case XK_slash: return KON_KEY_SLASH;
- case XK_backslash: return KON_KEY_BACKSLASH;
- case XK_grave: return KON_KEY_GRAVE;
-
- default: return KON_KEY_UNKNOWN;
- }
-}
-
-struct kon_context {
- Display *display;
-};
-
-bool kon_init(void) {
- kon_context_t *ctx = malloc(sizeof(kon_context_t));
- if (!ctx) return false;
- ctx->display = XOpenDisplay(NULL);
- if (!ctx->display) return false;
- kon_ctx = ctx;
- return true;
-}
-
-void kon_deinit(void) {
- if (!kon_ctx) return;
-
- XCloseDisplay(kon_ctx->display);
- free(kon_ctx);
- kon_ctx=NULL;
-}
-
-struct kon_window {
- Window window;
- GC gc;
- Visual *visual;
- int depth;
- Colormap colormap;
- bool owns_colormap;
- Atom wm_delete;
- bool shouldClose;
- int exitKey;
-};
-
-kon_window_t *kon_createWindow(const char *title, int x, int y, int width, int height, kon_windowFlags_t flags) {
- if (!kon_ctx) {
- fprintf(stderr, "kon_createWindow: There appears to be no kon_ctx. \nPlease, do kon_init(); before doing anything with konwinlib, thank you.\n");
- return NULL;
- }
-
- kon_window_t *window = malloc(sizeof(kon_window_t));
- if (!window) return NULL;
-
- int screen = DefaultScreen(kon_ctx->display);
-
- if (flags & KON_WINDOW_CENTER) {
- Window root = RootWindow(kon_ctx->display, screen);
-
- int mon_x = 0, mon_y = 0;
- int mon_width = DisplayWidth(kon_ctx->display, screen);
- int mon_height = DisplayHeight(kon_ctx->display, screen);
-
- Window root_ret, child_ret;
- int root_x, root_y, win_x, win_y;
- unsigned int mask;
- XQueryPointer(kon_ctx->display, root, &root_ret, &child_ret, &root_x, &root_y, &win_x, &win_y, &mask);
-
- XRRScreenResources *res = XRRGetScreenResourcesCurrent(kon_ctx->display, root);
- if (res) {
- for (int i = 0; i < res->noutput; i++) {
- XRROutputInfo *out_info = XRRGetOutputInfo(kon_ctx->display, res, res->outputs[i]);
-
- if (out_info && out_info->crtc) {
- XRRCrtcInfo *crtc = XRRGetCrtcInfo(kon_ctx->display, res, out_info->crtc);
- if (crtc) {
-
- if (root_x >= crtc->x && root_x < crtc->x + (int)crtc->width &&
- root_y >= crtc->y && root_y < crtc->y + (int)crtc->height) {
- mon_x = crtc->x;
- mon_y = crtc->y;
- mon_width = crtc->width;
- mon_height = crtc->height;
- XRRFreeCrtcInfo(crtc);
- if (out_info) XRRFreeOutputInfo(out_info);
- break;
- }
- XRRFreeCrtcInfo(crtc);
- }
- }
- if (out_info) XRRFreeOutputInfo(out_info);
- }
- XRRFreeScreenResources(res);
- }
-
- x = mon_x + (mon_width - width ) / 2;
- y = mon_y + (mon_height - height) / 2;
- }
-
- if (flags & KON_WINDOW_TRANSPARENT) {
- XVisualInfo vinfo;
- if (!XMatchVisualInfo(kon_ctx->display, screen, 32, TrueColor, &vinfo)) {
- free(window);
- return NULL;
- }
-
- window->visual = vinfo.visual;
- window->depth = vinfo.depth;
- window->colormap = XCreateColormap(kon_ctx->display, RootWindow(kon_ctx->display, screen), window->visual, AllocNone);
-
- XSetWindowAttributes attrs;
- attrs.colormap = window->colormap;
- attrs.background_pixel = 0;
- attrs.border_pixel = 0;
-
- window->window = XCreateWindow(
- kon_ctx->display, RootWindow(kon_ctx->display, screen),
- x, y, width, height, 0, window->depth, InputOutput,
- window->visual, CWColormap | CWBackPixel | CWBorderPixel, &attrs);
-
- window->owns_colormap = true;
- } else {
- window->visual = DefaultVisual(kon_ctx->display, screen);
- window->depth = DefaultDepth(kon_ctx->display, screen);
- window->colormap = DefaultColormap(kon_ctx->display, screen);
-
- window->window = XCreateSimpleWindow(
- kon_ctx->display, RootWindow(kon_ctx->display, screen),
- x, y, width, height, 0, 0, 0);
-
- window->owns_colormap = false;
- }
-
- if (!window->window) {
- if (window->owns_colormap) {
- XFreeColormap(kon_ctx->display, window->colormap);
- }
- free(window);
- return NULL;
- }
-
- XStoreName(kon_ctx->display, window->window, title);
- XSelectInput(kon_ctx->display, window->window, ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
-
- if (flags & KON_WINDOW_NO_DECOR) {
- Atom motif_hints = XInternAtom(kon_ctx->display, "_MOTIF_WM_HINTS", False);
- struct { unsigned long flags, functions, decorations; long input_mode; unsigned long status; } hints;
- memset(&hints, 0, sizeof(hints));
- hints.flags = 2;
- hints.decorations = 0;
- XChangeProperty(kon_ctx->display, window->window, motif_hints,
- motif_hints, 32, PropModeReplace, (unsigned char *)&hints, 5);
- }
-
- if (flags & KON_WINDOW_ALWAYS_ONTOP) {
- Atom wm_state = XInternAtom(kon_ctx->display, "_NET_WM_STATE", False);
- Atom wm_above = XInternAtom(kon_ctx->display, "_NET_WM_STATE_ABOVE", False);
- XChangeProperty(kon_ctx->display, window->window, wm_state, XA_ATOM, 32,
- PropModeReplace, (unsigned char *)&wm_above, 1);
- }
-
- if (!(flags & KON_WINDOW_RESIZABLE)) {
- XSizeHints hints;
- hints.flags = PMinSize | PMaxSize;
- hints.min_width = hints.max_width = width;
- hints.min_height = hints.max_height = height;
- XSetWMNormalHints(kon_ctx->display, window->window, &hints);
- }
-
- window->wm_delete = XInternAtom(kon_ctx->display, "WM_DELETE_WINDOW", False);
- XSetWMProtocols(kon_ctx->display, window->window, &window->wm_delete, 1);
-
- window->gc = XCreateGC(kon_ctx->display, window->window, 0, NULL);
-
- XMapWindow(kon_ctx->display, window->window);
- XFlush(kon_ctx->display);
-
- window->exitKey = 0;
-
- window->shouldClose = false;
-
- return window;
-}
-
-void kon_destroyWindow(kon_window_t *window) {
- if (!window) return;
- if (!kon_ctx) { free(window); return; }
-
- if (window->gc) XFreeGC(kon_ctx->display, window->gc);
- if (window->window) XDestroyWindow(kon_ctx->display, window->window);
- if (window->owns_colormap && window->colormap) XFreeColormap(kon_ctx->display, window->colormap);
-
- XFlush(kon_ctx->display);
-
- free(window);
-}
-
-void kon_setExitKey(kon_window_t *window, int key) {
- if (!window) return;
- window->exitKey = key;
-}
-
-void kon_setWindowPos(kon_window_t *window, int x, int y) {
- if (!window || !kon_ctx) return;
-
- XMoveWindow(kon_ctx->display, window->window, x, y);
- XFlush(kon_ctx->display);
-}
-
-void kon_setWindowSize(kon_window_t *window, int width, int height) {
- if (!window || !kon_ctx) return;
-
- XResizeWindow(kon_ctx->display, window->window, width, height);
- XFlush(kon_ctx->display);
-}
-
-void kon_getWindowPos(kon_window_t *window, int *x, int *y) {
- if (!window || !kon_ctx || !x || !y) return;
-
- Window child;
- XTranslateCoordinates(kon_ctx->display, window->window, RootWindow(kon_ctx->display, DefaultScreen(kon_ctx->display)),
- 0, 0, x, y, &child);
-}
-
-void kon_getWindowSize(kon_window_t *window, int *width, int *height) {
- if (!window || !kon_ctx || !width || !height) return;
-
- XWindowAttributes attrs;
- XGetWindowAttributes(kon_ctx->display, window->window, &attrs);
- *width = attrs.width;
- *height = attrs.height;
-}
-
-int kon_pollEvent(kon_window_t *window, kon_event_t *event) {
- if (!window || !kon_ctx || !event) return 0;
-
- event->type = KON_EVENT_NONE;
-
- if (!XPending(kon_ctx->display)) return 0;
-
- XEvent xev;
- XNextEvent(kon_ctx->display, &xev);
-
- if (xev.type == ClientMessage) {
- if ((Atom)xev.xclient.data.l[0] == window->wm_delete) {
- event->type = KON_EVENT_CLOSE;
- window->shouldClose = true;
- }
- }
-
- if (xev.type == ConfigureNotify) {
- event->type = KON_EVENT_RESIZE;
- event->width = xev.xconfigure.width;
- event->height = xev.xconfigure.height;
- return 1;
- }
-
- if (xev.type == KeyPress) {
- event->type = KON_EVENT_KEY_DOWN;
- event->key = (int)kon_translateX11Key_(XLookupKeysym(&xev.xkey, 0));
- if (window->exitKey != 0 && event->key == window->exitKey) {
- window->shouldClose = true;
- }
- return 1;
- }
-
- if (xev.type == KeyRelease) {
- event->type = KON_EVENT_KEY_UP;
- event->key = (int)kon_translateX11Key_(XLookupKeysym(&xev.xkey, 0));
- return 1;
- }
-
- if (xev.type == ButtonPress || xev.type == ButtonRelease) {
- int konButton = -1;
- switch (xev.xbutton.button) {
- case Button1:
- konButton = KON_MOUSE_LEFT;
- break;
- case Button2:
- konButton = KON_MOUSE_MIDDLE;
- break;
- case Button3:
- konButton = KON_MOUSE_RIGHT;
- break;
- default:
- break;
- }
-
- if (konButton != -1) {
- event->type = (xev.type == ButtonPress) ? KON_EVENT_MOUSE_DOWN : KON_EVENT_MOUSE_UP;
- event->mouseButton = (kon_mouseButton_t)konButton;
- event->mouseX = xev.xbutton.x;
- event->mouseY = xev.xbutton.y;
- }
- return 1;
- }
-
- if (xev.type == MotionNotify) {
- event->type = KON_EVENT_MOUSE_MOVE;
- event->mouseX = xev.xmotion.x;
- event->mouseY = xev.xmotion.y;
- return 1;
- }
-
- return 1;
-}
-
-bool kon_windowShouldClose(kon_window_t *window) {
- if (!window || !kon_ctx) return true;
- return window->shouldClose;
-}
-
-/* TODO: implement the rest of these */
-
-void kon_blitPixels(kon_window_t *window, const uint32_t *pixels, int width, int height) {
- if (!window || !kon_ctx || !pixels) return;
-
- XImage *ximg = XCreateImage(kon_ctx->display, window->visual, window->depth, ZPixmap, 0, (char *)pixels, width, height, 32, 0);
- if (!ximg) return;
-
- XPutImage(kon_ctx->display, window->window, window->gc, ximg, 0, 0, 0, 0, width, height);
-
- ximg->data = NULL;
- XDestroyImage(ximg);
-
- XFlush(kon_ctx->display);
-}
-
-/*** windows implementation ***/
-
-#elif defined(_WIN32)
-
-#include <windows.h>
-#include <string.h>
-
-struct kon_context {
- HINSTANCE hInstance;
-};
-
-struct kon_window {
- HWND hwnd;
- bool shouldClose;
- bool isTransparent;
- int exitKey;
- kon_eventQueue_t queue;
-};
-
-static kon_key_t kon_translateWin32Key_(WPARAM vk, LPARAM lParam) {
- if (vk == VK_SHIFT) {
- UINT scancode = (lParam >> 16) & 0xFF;
- UINT lshift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
- return (scancode == lshift) ? KON_KEY_LEFT_SHIFT : KON_KEY_RIGHT_SHIFT;
- }
- if (vk == VK_CONTROL) {
- return (lParam & 0x01000000) ? KON_KEY_RIGHT_CTRL : KON_KEY_LEFT_CTRL;
- }
- if (vk == VK_MENU) {
- return (lParam & 0x01000000) ? KON_KEY_RIGHT_ALT : KON_KEY_LEFT_ALT;
- }
-
- switch (vk) {
- case 'A': return KON_KEY_A;
- case 'B': return KON_KEY_B;
- case 'C': return KON_KEY_C;
- case 'D': return KON_KEY_D;
- case 'E': return KON_KEY_E;
- case 'F': return KON_KEY_F;
- case 'G': return KON_KEY_G;
- case 'H': return KON_KEY_H;
- case 'I': return KON_KEY_I;
- case 'J': return KON_KEY_J;
- case 'K': return KON_KEY_K;
- case 'L': return KON_KEY_L;
- case 'M': return KON_KEY_M;
- case 'N': return KON_KEY_N;
- case 'O': return KON_KEY_O;
- case 'P': return KON_KEY_P;
- case 'Q': return KON_KEY_Q;
- case 'R': return KON_KEY_R;
- case 'S': return KON_KEY_S;
- case 'T': return KON_KEY_T;
- case 'U': return KON_KEY_U;
- case 'V': return KON_KEY_V;
- case 'W': return KON_KEY_W;
- case 'X': return KON_KEY_X;
- case 'Y': return KON_KEY_Y;
- case 'Z': return KON_KEY_Z;
-
- case '0': return KON_KEY_0;
- case '1': return KON_KEY_1;
- case '2': return KON_KEY_2;
- case '3': return KON_KEY_3;
- case '4': return KON_KEY_4;
- case '5': return KON_KEY_5;
- case '6': return KON_KEY_6;
- case '7': return KON_KEY_7;
- case '8': return KON_KEY_8;
- case '9': return KON_KEY_9;
-
- case VK_F1: return KON_KEY_F1;
- case VK_F2: return KON_KEY_F2;
- case VK_F3: return KON_KEY_F3;
- case VK_F4: return KON_KEY_F4;
- case VK_F5: return KON_KEY_F5;
- case VK_F6: return KON_KEY_F6;
- case VK_F7: return KON_KEY_F7;
- case VK_F8: return KON_KEY_F8;
- case VK_F9: return KON_KEY_F9;
- case VK_F10: return KON_KEY_F10;
- case VK_F11: return KON_KEY_F11;
- case VK_F12: return KON_KEY_F12;
-
- case VK_LEFT: return KON_KEY_LEFT;
- case VK_RIGHT: return KON_KEY_RIGHT;
- case VK_UP: return KON_KEY_UP;
- case VK_DOWN: return KON_KEY_DOWN;
-
- case VK_SPACE: return KON_KEY_SPACE;
- case VK_RETURN: return KON_KEY_ENTER;
- case VK_TAB: return KON_KEY_TAB;
- case VK_BACK: return KON_KEY_BACKSPACE;
- case VK_ESCAPE: return KON_KEY_ESCAPE;
- case VK_DELETE: return KON_KEY_DELETE;
-
- case VK_OEM_MINUS: return KON_KEY_MINUS;
- case VK_OEM_PLUS: return KON_KEY_EQUAL;
- case VK_OEM_4: return KON_KEY_LEFT_BRACKET;
- case VK_OEM_6: return KON_KEY_RIGHT_BRACKET;
- case VK_OEM_1: return KON_KEY_SEMICOLON;
- case VK_OEM_7: return KON_KEY_APOSTROPHE;
- case VK_OEM_COMMA: return KON_KEY_COMMA;
- case VK_OEM_PERIOD: return KON_KEY_PERIOD;
- case VK_OEM_2: return KON_KEY_SLASH;
- case VK_OEM_5: return KON_KEY_BACKSLASH;
- case VK_OEM_3: return KON_KEY_GRAVE;
-
- default: return KON_KEY_UNKNOWN;
- }
-}
-
-LRESULT CALLBACK kon_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
- kon_window_t *window = (kon_window_t *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
-
- switch (msg) {
- case WM_NCCREATE: {
- CREATESTRUCT *cs = (CREATESTRUCT *)lParam;
- SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams);
- break;
- }
- case WM_KEYDOWN:
- if (window) {
- kon_event_t ev = {0};
- ev.type = KON_EVENT_KEY_DOWN;
- ev.key = (int)kon_translateWin32Key_(wParam, lParam);
- kon_pushEvent_(&window->queue, &ev);
- if (window->exitKey != 0 && ev.key == window->exitKey) {
- window->shouldClose = true;
- ev.type = KON_EVENT_CLOSE;
- kon_pushEvent_(&window->queue, &ev);
- }
- }
- break;
- case WM_KEYUP:
- if (window) {
- kon_event_t ev = {0};
- ev.type = KON_EVENT_KEY_UP;
- ev.key = (int)kon_translateWin32Key_(wParam, lParam);
- kon_pushEvent_(&window->queue, &ev);
- }
- break;
- case WM_LBUTTONDOWN: case WM_LBUTTONUP:
- case WM_RBUTTONDOWN: case WM_RBUTTONUP:
- case WM_MBUTTONDOWN: case WM_MBUTTONUP:
- if (window) {
- kon_event_t ev = {0};
- ev.type = (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN)
- ? KON_EVENT_MOUSE_DOWN : KON_EVENT_MOUSE_UP;
- ev.mouseButton = (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) ? KON_MOUSE_LEFT
- : (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONUP) ? KON_MOUSE_RIGHT
- : KON_MOUSE_MIDDLE;
- ev.mouseX = (int)(short)LOWORD(lParam);
- ev.mouseY = (int)(short)HIWORD(lParam);
- kon_pushEvent_(&window->queue, &ev);
- }
- break;
- case WM_MOUSEMOVE:
- if (window) {
- kon_event_t ev = {0};
- ev.type = KON_EVENT_MOUSE_MOVE;
- ev.mouseX = (int)(short)LOWORD(lParam);
- ev.mouseY = (int)(short)HIWORD(lParam);
- kon_pushEvent_(&window->queue, &ev);
- }
- break;
- case WM_CLOSE:
- if (window) {
- kon_event_t ev = {0};
- ev.type = KON_EVENT_CLOSE;
- window->shouldClose = true;
- kon_pushEvent_(&window->queue, &ev);
- }
- break;
- case WM_SIZE:
- /* minimizing reports 0x0, which would wreck the framebuffer */
- if (window && wParam != SIZE_MINIMIZED && LOWORD(lParam) > 0 && HIWORD(lParam) > 0) {
- kon_event_t ev = {0};
- ev.type = KON_EVENT_RESIZE;
- ev.width = LOWORD(lParam);
- ev.height = HIWORD(lParam);
- kon_pushEvent_(&window->queue, &ev);
- }
- break;
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- break;
- case WM_ERASEBKGND:
- return 1;
- }
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-bool kon_init(void) {
- kon_context_t *ctx = malloc(sizeof(kon_context_t));
- if (!ctx) return false;
-
- ctx->hInstance = GetModuleHandle(NULL);
-
- WNDCLASSEX wc = {0};
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.lpfnWndProc = kon_wndProc;
- wc.hInstance = ctx->hInstance;
- wc.lpszClassName = "KonWinLibClass";
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
-
- if (!RegisterClassEx(&wc)) {
- free(ctx);
- return false;
- }
-
- kon_ctx = ctx;
- return true;
-}
-
-void kon_deinit(void) {
- if (!kon_ctx) return;
-
- free(kon_ctx);
- kon_ctx = NULL;
-}
-
-
-kon_window_t *kon_createWindow(const char *title, int x, int y, int width, int height, kon_windowFlags_t flags) {
- if (!kon_ctx) return NULL;
-
- kon_window_t *window = calloc(1, sizeof(kon_window_t));
- if (!window) return NULL;
-
- window->isTransparent = (flags & KON_WINDOW_TRANSPARENT);
- window->exitKey = 0;
-
- DWORD style;
- if (flags & KON_WINDOW_NO_DECOR) {
- style = WS_POPUP;
- } else {
- style = WS_OVERLAPPEDWINDOW;
- if (!(flags & KON_WINDOW_RESIZABLE)) {
- style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
- }
- }
-
- DWORD exStyle = 0;
- if (flags & KON_WINDOW_ALWAYS_ONTOP) exStyle |= WS_EX_TOPMOST;
- if (flags & KON_WINDOW_TRANSPARENT) exStyle |= WS_EX_LAYERED;
-
- RECT adj = { 0, 0, width, height };
- AdjustWindowRectEx(&adj, style, FALSE, exStyle);
- int winW = adj.right - adj.left;
- int winH = adj.bottom - adj.top;
-
- if (flags & KON_WINDOW_CENTER) {
- POINT cursor;
- GetCursorPos(&cursor);
-
- HMONITOR hmon = MonitorFromPoint(cursor, MONITOR_DEFAULTTONEAREST);
-
- MONITORINFO mi;
- mi.cbSize = sizeof(MONITORINFO);
- GetMonitorInfo(hmon, &mi);
-
- int mon_x = mi.rcMonitor.left;
- int mon_y = mi.rcMonitor.top;
- int mon_width = mi.rcMonitor.right - mi.rcMonitor.left;
- int mon_height = mi.rcMonitor.bottom - mi.rcMonitor.top;
-
- x = mon_x + (mon_width - winW) / 2;
- y = mon_y + (mon_height - winH) / 2;
- }
-
- window->hwnd = CreateWindowEx(exStyle, "KonWinLibClass", title, style, x, y, winW, winH, NULL, NULL, kon_ctx->hInstance, window);
-
- if (!window->hwnd) {
- free(window);
- return NULL;
- }
-
- ShowWindow(window->hwnd, SW_SHOW);
-
- return window;
-}
-
-void kon_destroyWindow(kon_window_t *window) {
- if (!window) return;
- if (window->hwnd) DestroyWindow(window->hwnd);
- free(window);
-}
-
-bool kon_windowShouldClose(kon_window_t *window) {
- if (!window) return true;
- return window->shouldClose;
-}
-
-
-void kon_setExitKey(kon_window_t *window, int key) {
- if (!window) return;
- window->exitKey = key;
-}
-
-void kon_setWindowPos(kon_window_t *window, int x, int y) {
- if (!window || !kon_ctx) return;
-
- SetWindowPos(window->hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
-}
-
-void kon_setWindowSize(kon_window_t *window, int width, int height) {
- if (!window || !kon_ctx) return;
-
- RECT r = { 0, 0, width, height };
- AdjustWindowRectEx(&r, (DWORD)GetWindowLongPtr(window->hwnd, GWL_STYLE), FALSE, (DWORD)GetWindowLongPtr(window->hwnd, GWL_EXSTYLE));
- SetWindowPos(window->hwnd, NULL, 0, 0, r.right - r.left, r.bottom - r.top, SWP_NOMOVE | SWP_NOZORDER);
-}
-
-
-void kon_getWindowPos(kon_window_t *window, int *x, int *y) {
- if (!window || !x || !y) return;
-
- RECT rect;
- GetWindowRect(window->hwnd, &rect);
- *x = rect.left;
- *y = rect.top;
-}
-
-void kon_getWindowSize(kon_window_t *window, int *width, int *height) {
- if (!window || !width || !height) return;
-
- RECT rect;
- GetClientRect(window->hwnd, &rect);
- *width = rect.right - rect.left;
- *height = rect.bottom - rect.top;
-}
-
-int kon_pollEvent(kon_window_t *window, kon_event_t *event) {
- if (!window || !event) return 0;
-
- MSG msg;
- while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- if (!kon_popEvent_(&window->queue, event)) {
- event->type = KON_EVENT_NONE;
- return 0;
- }
- return 1;
-}
-
-void kon_blitPixels(kon_window_t *window, const uint32_t *pixels, int width, int height) {
- if (!window || !pixels) return;
-
- BITMAPINFO bmi = {0};
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = width;
- bmi.bmiHeader.biHeight = -height; /* top-down */
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
-
- if (window->isTransparent) {
- HDC screenDC = GetDC(NULL);
- HDC memDC = CreateCompatibleDC(screenDC);
-
- void *dibPixels;
- HBITMAP hbm = CreateDIBSection(screenDC, &bmi, DIB_RGB_COLORS, &dibPixels, NULL, 0);
- if (hbm) {
- memcpy(dibPixels, pixels, (size_t)width * height * 4);
- HBITMAP oldBmp = (HBITMAP)SelectObject(memDC, hbm);
-
- RECT winRect;
- GetWindowRect(window->hwnd, &winRect);
- POINT dstPos = { winRect.left, winRect.top };
- POINT srcPos = { 0, 0 };
- SIZE size = { width, height };
- BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
-
- UpdateLayeredWindow(window->hwnd, screenDC, &dstPos, &size, memDC, &srcPos, 0, &blend, ULW_ALPHA);
-
- SelectObject(memDC, oldBmp);
- DeleteObject(hbm);
- }
-
- DeleteDC(memDC);
- ReleaseDC(NULL, screenDC);
- } else {
- HDC winDC = GetDC(window->hwnd);
- SetDIBitsToDevice(winDC, 0, 0, width, height, 0, 0, 0, height, pixels, &bmi, DIB_RGB_COLORS);
- ReleaseDC(window->hwnd, winDC);
- }
-}
-
-#else
- #error "konwinlib.h: unsupported platform"
-#endif /* end of platform switch */
-
-/*** main loop ***/
-
-#ifdef __EMSCRIPTEN__
-
-typedef struct {
- kon_window_t *window;
- kon_mainLoopFn callback;
- void *userData;
-} kon_mainLoopCtx_;
-
-static void kon_mainLoopTrampoline_(void *arg) {
- kon_mainLoopCtx_ *ctx = (kon_mainLoopCtx_ *)arg;
-
- if (kon_windowShouldClose(ctx->window)) {
- emscripten_cancel_main_loop();
- free(ctx);
- return;
- }
-
- ctx->callback(ctx->userData);
-}
-
-void kon_runMainLoop(kon_window_t *window, kon_mainLoopFn callback, void *userData) {
- kon_mainLoopCtx_ *ctx = malloc(sizeof(kon_mainLoopCtx_));
- if (!ctx) return;
-
- ctx->window = window;
- ctx->callback = callback;
- ctx->userData = userData;
-
- emscripten_set_main_loop_arg(kon_mainLoopTrampoline_, ctx, 0, 1);
-}
-
-#else
-
-void kon_runMainLoop(kon_window_t *window, kon_mainLoopFn callback, void *userData) {
- while (!kon_windowShouldClose(window)) {
- callback(userData);
- }
-}
-
-#endif /* __EMSCRIPTEN__ */
-
-#endif /* end of KONWINLIB_IMPLEMENTATION */
-
-#endif