ボタン押すフィードバックの修正

This commit is contained in:
2026-01-19 22:19:35 +09:00
parent 432a81c997
commit 0abfbe1c8e
3 changed files with 255 additions and 50 deletions

View File

@@ -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);

View File

@@ -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 <windows.h>
#define SUWAUI_WINDOWS
#elif defined(__unix__) || defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sunos) || defined(__apple__)
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
#include <X11/Xatom.h>
#define SUWAUI_UNIX
#endif
#include <stdio.h>
#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

20
main.c
View File

@@ -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