From 0abfbe1c8e7da15f2da9092a04a480ce7babe239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AB=8F=E8=A8=AA=E5=AD=90?= Date: Mon, 19 Jan 2026 22:19:35 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=9C=E3=82=BF=E3=83=B3=E6=8A=BC=E3=81=99?= =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=BC=E3=83=89=E3=83=90=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- control.h | 6 +- include/suwaui.h | 279 ++++++++++++++++++++++++++++++++++++++++------- main.c | 20 ++-- 3 files changed, 255 insertions(+), 50 deletions(-) diff --git a/control.h b/control.h index 8dabbfd..8ea1568 100644 --- a/control.h +++ b/control.h @@ -43,8 +43,8 @@ typedef struct { SuwaLabel *problem; } CtrlLabels; -void control_expose(SuwaWindow *window, CtrlLabels *labels); -void handle_button_press(SuwaWindow *window, int mx, int my); +void control_expose(SuwaWindow *window, CtrlLabels *labels, SuwaButton *button); +void handle_button_press(SuwaWindow *window, CtrlLabels *labels, int mx, int my); void handle_button_release(SuwaWindow *window, CtrlLabels *labels, int mx, int my); void handle_key_press(SuwaWindow *window, CtrlLabels *labels); -// void handle_mouse_hover(SuwaWindow *window); +// void handle_mouse_hover(SuwaWindow *window, CtrlLabels *labels); diff --git a/include/suwaui.h b/include/suwaui.h index c8cc5da..b350777 100644 --- a/include/suwaui.h +++ b/include/suwaui.h @@ -21,25 +21,81 @@ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTIO CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************************/ -#pragma once +#ifndef SUWAUI_H +#define SUWAUI_H +#if defined(_WIN32) || defined(_WIN64) +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#else +#define WIN64_LEAN_AND_MEAN +#endif +#include +#define SUWAUI_WINDOWS +#elif defined(__unix__) || defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sunos) || defined(__apple__) #include #include #include +#define SUWAUI_UNIX +#endif #include -#define FGCOL 0xfcfcfc +#define COLOR_WHITE 0xfcfcfc #if defined(__OpenBSD__) -#define BGCOL 0x232320 -#define BTSEL 0xb8b515 -#define BTCOL 0xf1ed25 -#define BTHVR 0xecea71 +#define COLOR_BD 0x232320 // color black decimal +#define COLOR_BS "#232320" // color black string +#define COLOR_DD 0xb8b515 // color dark decimal +#define COLOR_DS "#b8b515" // color dark string +#define COLOR_ND 0xf1ed25 // color normal decimal +#define COLOR_NS "#f1ed25" // color normal string +#define COLOR_LD 0xecea71 // color light decimal +#define COLOR_LS "#ecea71" // color light string #elif defined(__FreeBSD__) -#define BGCOL 0x232020 -#define BTSEL 0xb61729 -#define BTCOL 0xee4030 -#define BTHVR 0xf35869 +#define COLOR_BD 0x232020 // color black decimal +#define COLOR_BS "#232020" // color black string +#define COLOR_DD 0xb61729 // color dark decimal +#define COLOR_DS "#b61729" // color dark string +#define COLOR_ND 0xee4030 // color normal decimal +#define COLOR_NS "#ee4030" // color normal string +#define COLOR_LD 0xf35869 // color light decimal +#define COLOR_LS "#f35869" // color light string +#elif defined(__NetBSD__) +#define COLOR_BD 0x232018 // color black decimal +#define COLOR_BS "#232018" // color black string +#define COLOR_DD 0xac7718 // color dark decimal +#define COLOR_DS "#ac7718" // color dark string +#define COLOR_ND 0xf7a717 // color normal decimal +#define COLOR_NS "#f7a717" // color normal string +#define COLOR_LD 0xf8c56a // color light decimal +#define COLOR_LS "#f8c56a" // color light string +#elif defined(SUWAUI_WINDOWS) +#define COLOR_BD 0x202023 // color black decimal +#define COLOR_BS "#202023" // color black string +#define COLOR_DD 0x1a6ecf // color dark decimal +#define COLOR_DS "#1a6ecf" // color dark string +#define COLOR_ND 0x2687f7 // color normal decimal +#define COLOR_NS "#2687f7" // color normal string +#define COLOR_LD 0x6aa6eb // color light decimal +#define COLOR_LS "#6aa6eb" // color light string +#elif defined(__apple__) +#define COLOR_BD 0x232323 // color black decimal +#define COLOR_BS "#232323" // color black string +#define COLOR_DD 0x746c74 // color dark decimal +#define COLOR_DS "#746c74" // color dark string +#define COLOR_ND 0x988f98 // color normal decimal +#define COLOR_NS "#988f98" // color normal string +#define COLOR_LD 0xbdb4bd // color light decimal +#define COLOR_LS "#bdb4bd" // color light string +#elif defined(__sunos) +#define COLOR_BD 0x182023 // color black decimal +#define COLOR_BS "#182023" // color black string +#define COLOR_DD 0x1cbcd0 // color dark decimal +#define COLOR_DS "#1cbcd0" // color dark string +#define COLOR_ND 0x29d3ff // color normal decimal +#define COLOR_NS "#29d3ff" // color normal string +#define COLOR_LD 0x8ae5ff // color light decimal +#define COLOR_LS "#8ae5ff" // color light string #endif #if defined(__cplusplus) @@ -55,6 +111,13 @@ typedef struct { int isrunning; const char *name; const char *version; +#if defined(SUWAUI_WINDOWS) + HWND hwnd; + HDC hdc_mem; + HBITMAP backbitmap; + HFONT hfont; + COLORREF fg_color; +#elif defined(SUWAUI_UNIX) const char *res_name; const char *class_name; Display *display; @@ -68,18 +131,91 @@ typedef struct { Colormap colormap; Pixmap backbuf; XEvent event; +#endif } SuwaWindow; __attribute__((unused)) static void suwaui_destroy_window(SuwaWindow *w); __attribute__((unused)) static inline float get_scale(SuwaWindow *w) { +#if defined(SUWAUI_WINDOWS) +#elif defined(SUWAUI_UNIX) XWindowAttributes attr; XGetWindowAttributes(w->display, w->xwindow, &attr); float sx = (float)attr.width / w->start_width; float sy = (float)attr.height / w->start_height; +#endif return sx < sy ? sx : sy; } +#if defined(SUWAUI_WINDOWS) +LRESULT CALLBACK SuwaWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + SuwaWindow *w = (SuwaWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch (msg) { + case WM_CREATE: + LPCREATESTRUCT cs = (LPCREATESTRUCT)lParam; + w = (SuwaWindow *)cs->lpCreateParams; + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)w); + return 0 + case WM_SIZE: + if (w == NULL) break; + + int new_w = LOWORD(lParam); + int new_h = HIWORD(lParam); + + if (w->back_bitmap != NULL) { + DeleteObject(w->back_bitmap); + w->back_bitmap = NULL; + } + + HDC hdc = GetDC(hwnd); + if (hdc) { + w->back_bitmap = CreateCompatibleBitmap(hdc, new_w, new_h); + if (w->back_bitmap) { + SelectObject(w->hdc_memm, w->back_bitmap); + } + ReleaseDC(hwnd, hdc); + } + + w->width = new_w; + w->height = new_h; + + InvalidateRect(hwnd, NULL, FALSE); + return 0; + case WM_PAINT: + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + if (w && w->hdc_mem) { + RECT client; + GetClientRect(hwnd, &client); + FillRect(w->hdc_mem, &client, (HBRUSH)GetStockObject(COLOR_BD)); + + // suwaui_on_draw(w); + + BitBlt(hdc, 0, 0, w->width, w->height, w->hdc_mem, 0, 0, SRCCOPY); + } + + EndPaint(hwnd, &ps); + return 0; + // case WM_ERASEBKGND: + // return 1; + // case WM_LBUTTONDOWN: + // case WM_LBUTTONUP: + // case WM_MOUSEMOVE: + // case WM_KEYDOWN: + // case WM_KEYUP: + case WM_DESTROY: + PostQuitMessage(0); + return 0; + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} +#endif + __attribute__((unused)) static SuwaWindow suwaui_create_window(int x, int y, int width, int height, const char *software_name, const char *software_version, const char *res_name, const char *class_name, @@ -88,23 +224,46 @@ __attribute__((unused)) static SuwaWindow suwaui_create_window(int x, int y, int (void)cannot_grow; SuwaWindow w = {0}; + w.isrunning = 1; w.width = width; w.height = height; w.start_width = width; w.start_height = height; w.name = software_name; w.version = software_version; +#if defined(SUWAUI_WINDOWS) + WNDCLASSEX wc = { sizeof(WNDCLASSEX) }; + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = SuwaWindowsProc; + wc.hInstance = GetModuleHandle(NULL); + wc.hCursor = LoadCursor(NULL, IDCARROW); + wc.hbrBackground = NULL; + wc.lpszClassName = TEXT("SuwaWindowClass"); + + RegisterClassEx(&wc); + + DWORD style = WS_OVERLAPPEDWINDOW; + + w.hwnd = CreateWindowEx(0, wc.lpszClassName, name, style, + x, y, width, height, NULL, NULL, wc.hInstance, NULL); + if (!w.hwnd) return (SUwaWindow){0}; + + HDC hdc = GetDC(w.hwnd); + w.hdc_mem = CreateCompatibleDC(hdc); + w.back_bitmap = CreateCompatibleBitmap(hdc, width, height); + SelectObject(w.hdc_mem, w.back_bitmap); + ReleaseDC(w.hwnd, hdc); + + ShowWindow(w.hwnd, hdc); + UpdateWindow(w.hwnd); +#elif defined(SUWAUI_UNIX) w.res_name = res_name; w.class_name = class_name; - w.isrunning = 1; XGCValues values; w.display = XOpenDisplay(NULL); - if (w.display == NULL) { - fprintf(stderr, "screen open fail\n"); - return (SuwaWindow){0}; - } + if (w.display == NULL) return (SuwaWindow){0}; w.screen = DefaultScreen(w.display); @@ -122,10 +281,9 @@ __attribute__((unused)) static SuwaWindow suwaui_create_window(int x, int y, int RootWindow(w.display, w.screen), w.x, w.y, w.width, w.height, - 1, BTCOL, BGCOL); + 1, COLOR_ND, COLOR_BD); if (!w.xwindow) { suwaui_destroy_window(&w); - fprintf(stderr, "window create fail\n"); return (SuwaWindow){0}; } @@ -167,22 +325,21 @@ __attribute__((unused)) static SuwaWindow suwaui_create_window(int x, int y, int XFree(classHint); } - XSetWindowBackground(w.display, w.xwindow, BGCOL); + XSetWindowBackground(w.display, w.xwindow, COLOR_BD); XSelectInput(w.display, w.xwindow, ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask - // | PointerMotionMask - // | ButtonMotionMask + | PointerMotionMask + | ButtonMotionMask // | StructureNotifyMask ); w.gc = XCreateGC(w.display, w.xwindow, 0, &values); if (!w.gc) { suwaui_destroy_window(&w); - fprintf(stderr, "gc create fail\n"); return (SuwaWindow){0}; } @@ -192,28 +349,31 @@ __attribute__((unused)) static SuwaWindow suwaui_create_window(int x, int y, int &w.visual, AllocNone); if (w.colormap == None) { suwaui_destroy_window(&w); - fprintf(stderr, "calor map create fail\n"); return (SuwaWindow){0}; } w.font = XftFontOpenName(w.display, w.screen, font); if (!w.font) { suwaui_destroy_window(&w); - fprintf(stderr, "font create fail\n"); return (SuwaWindow){0}; } if (!XftColorAllocName(w.display, &w.visual, w.colormap, fg_color, &w.color)) { suwaui_destroy_window(&w); - fprintf(stderr, "color estimate fail\n"); return (SuwaWindow){0}; } +#endif return w; } __attribute__((unused)) static void suwaui_destroy_window(SuwaWindow *w) { +#if defined(SUWAUI_WINDOWS) + if (w->back_bitmap) DeleteObject(w->back_bitmap); + if (w->hdc_mem) DeleteDC(w->hdc_mem); + if (w->hwnd) DestroyWindow(w->hwnd); +#elif defined(SUWAUI_UNIX) if (w->font) XftFontClose(w->display, w->font); if (w->gc) XFreeGC(w->display, w->gc); @@ -223,27 +383,22 @@ __attribute__((unused)) static void suwaui_destroy_window(SuwaWindow *w) { } if (w->xwindow) XDestroyWindow(w->display, w->xwindow); if (w->display) XCloseDisplay(w->display); +#endif + + *w = (SuwaWindow){0}; } #endif // SUWAUI_IMPLEMENTS_SUWAWINDOW -#if defined(SUWAUI_IMPLEMENTS_SUWATABS) -typedef struct { - int x, y, width, height; -} SuwaTab; - -typedef struct { - int x, y, width, height; -} SuwaTabs; -#endif // SUWAUI_IMPLEMENTS_SUWATABS - #if defined(SUWAUI_IMPLEMENTS_SUWABUTTON) typedef struct { int x, y, width, height; + int row, col; const char *text; XftFont *font; - int bg_color; + unsigned long bg_color; XftColor fg_color; int pressed; // 0 = 普通、1 = 押している + int hovered; } SuwaButton; // __attribute__((unused)) static void suwaui_del_button(SuwaWindow *window, SuwaButton *button); @@ -259,7 +414,10 @@ __attribute__((unused)) static XftColor suwaui_set_button_fgcolor(SuwaWindow *wi } __attribute__((unused)) static void suwaui_draw_button(SuwaWindow *window, SuwaButton *btn, XftDraw *xftdraw) { - unsigned long curbg = btn->pressed ? BTSEL : btn->bg_color; + unsigned long curbg; + if (btn->pressed) curbg = COLOR_DD; + else if (btn->hovered) curbg = COLOR_LD; + else curbg = btn->bg_color; XSetForeground(window->display, window->gc, curbg); XFillRectangle(window->display, window->target, window->gc, btn->x, btn->y, btn->width, btn->height); @@ -284,7 +442,7 @@ __attribute__((unused)) static void suwaui_draw_button(SuwaWindow *window, SuwaB } __attribute__((unused)) static SuwaButton suwaui_add_button(int x, int y, int width, int height, - const char *text, XftFont *font, int bg_color, XftColor fg_color) { + const char *text, XftFont *font, unsigned long bg_color, XftColor fg_color) { SuwaButton button = { .x = x, .y = y, @@ -365,3 +523,50 @@ __attribute__((unused)) static void suwaui_del_label(SuwaWindow *window, SuwaLab #if defined(__cplusplus) } #endif + +#if defined(SUWAUI_IMPLEMENTS_SUWATABS) +typedef struct { + int x, y, width, height; +} SuwaTab; + +typedef struct { + int x, y, width, height; +} SuwaTabs; +#endif // SUWAUI_IMPLEMENTS_SUWATABS + +#if defined(SUWAUI_IMPLEMENTS_SUWASIDE) +typedef struct { + int x, y, width, height; +} SuwaSide; +#endif // SUWAUI_IMPLEMENTS_SUWASIDE + +#if defined(SUWAUI_IMPLEMENTS_SUWATEXTBOX) +typedef struct { + int x, y, width, height; +} SuwaTextbox; +#endif // SUWAUI_IMPLEMENTS_SUWATEXTBOX + +#if defined(SUWAUI_IMPLEMENTS_SUWATEXTEDIT) +typedef struct { + int x, y, width, height; +} SuwaTextEdit; +#endif // SUWAUI_IMPLEMENTS_SUWATEXTEDIT + +#if defined(SUWAUI_IMPLEMENTS_SUWAMENUBAR) +typedef struct { + int x, y, width, height; +} SuwaMenubar; +#endif // SUWAUI_IMPLEMENTS_SUWAMENUBAR + +#if defined(SUWAUI_IMPLEMENTS_SUWADIALOG) +typedef struct { + int x, y, width, height; +} SuwaDialog; +#endif // SUWAUI_IMPLEMENTS_SUWADIALOG + +#if defined(SUWAUI_IMPLEMENTS_SUWAIO) +typedef struct { + int x, y, width, height; +} SuwaIO; +#endif // SUWAUI_IMPLEMENTS_SUWAIO +#endif // SUWAUI_H diff --git a/main.c b/main.c index f12daf9..acb942d 100644 --- a/main.c +++ b/main.c @@ -48,22 +48,22 @@ int main() { SuwaWindow window = suwaui_create_window( 500, 400, 382, 534, disname, version, "unixcalc", "UnixCalc", - "Noto Sans CJK-8", "#232320", + "Noto Sans CJK-8", COLOR_BS, 0, 1, 0); SuwaLabel resLabel = suwaui_add_label(&window, 20, 180, 0, 0, "0", - "Noto Sans CJK-48", "#f1ed25", 1); + "Noto Sans CJK-48", COLOR_NS, 1); SuwaLabel problemLabel = suwaui_add_label(&window, 20, 80, 0, 0, "", - "Noto Sans CJK-12", "#b8b515", 1); + "Noto Sans CJK-12", COLOR_DS, 1); #elif defined(__FreeBSD__) SuwaWindow window = suwaui_create_window( 20, 40, 382, 534, disname, version, "unixcalc", "UnixCalc", - "Noto Sans CJK-12", "#232020", + "Noto Sans CJK-12", COLOR_BS, 0, 1, 0); SuwaLabel resLabel = suwaui_add_label(&window, 20, 180, 0, 0, "0", - "Noto Sans CJK-72", "#ee4030", 1); + "Noto Sans CJK-72", COLOR_NS, 1); SuwaLabel problemLabel = suwaui_add_label(&window, 20, 80, 0, 0, "", - "Noto Sans CJK-24", "#b61729", 1); + "Noto Sans CJK-24", COLOR_DS, 1); #endif CtrlLabels lbl = { @@ -79,7 +79,7 @@ int main() { fake.xexpose.window = window.xwindow; fake.xexpose.width = attr.width; fake.xexpose.height = attr.height; - control_expose(&window, &lbl); + control_expose(&window, &lbl, &(SuwaButton){0}); } while (window.isrunning) { @@ -89,13 +89,13 @@ int main() { case Expose: case ConfigureNotify: XClearWindow(window.display, window.xwindow); - control_expose(&window, &lbl); + control_expose(&window, &lbl, &(SuwaButton){0}); break; case ButtonPress: if (window.event.xbutton.button == Button1) { int x = window.event.xbutton.x; int y = window.event.xbutton.y; - handle_button_press(&window, x, y); + handle_button_press(&window, &lbl, x, y); break; } case ButtonRelease: @@ -109,7 +109,7 @@ int main() { handle_key_press(&window, &lbl); break; // case MotionNotify: - // handle_mouse_hover(&window); + // handle_mouse_hover(&window, &lbl); // break; case ClientMessage: // WM_DELETE_WINDOW