/* hello.c — minimal SkyKit application template * * Build: * cd skykit && make (builds libskykit.a) * cd template * gcc -O2 hello.c -I.. -L.. -lskykit \ * $(pkg-config --libs --cflags x11 xft fontconfig) -o hello * * This template shows the minimum boilerplate for a native OrionOS app: * - sk_app_init() opens the display and loads fonts * - Create a window and a Pixmap back-buffer * - Wrap them in an SKPainter * - Draw to the Pixmap, then XCopyArea to the window * - Respond to Expose, KeyPress, ButtonPress, ClientMessage */ #include #include #include #include #include #include #include "skykit.h" #define WIN_W 640 #define WIN_H 400 int main(void) { SKApp app; sk_app_init(&app); /* ── Window ──────────────────────────────────────────── */ XSetWindowAttributes swa = { .background_pixel = sk_color(&app, SK_BG), .event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask, }; Window win = XCreateWindow( app.dpy, app.root, 200, 100, WIN_W, WIN_H, 0, app.depth, InputOutput, app.vis, CWBackPixel | CWEventMask, &swa); /* Back-buffer for flicker-free rendering */ GC gc = XCreateGC(app.dpy, win, 0, NULL); Pixmap buf = XCreatePixmap(app.dpy, win, WIN_W, WIN_H, app.depth); /* SKPainter wraps the back-buffer */ SKPainter p = { .app = &app, .drw = buf, .gc = gc }; /* WM_DELETE_WINDOW protocol */ Atom wm_del = XInternAtom(app.dpy, "WM_DELETE_WINDOW", False); XSetWMProtocols(app.dpy, win, &wm_del, 1); XStoreName(app.dpy, win, "Hello OrionOS"); XClassHint *ch = XAllocClassHint(); if (ch) { ch->res_name = (char*)"hello"; ch->res_class = (char*)"Hello"; XSetClassHint(app.dpy, win, ch); XFree(ch); } XMapWindow(app.dpy, win); XFlush(app.dpy); /* Click counter for demo */ int clicks = 0; /* ── Draw function ───────────────────────────────────── */ /* We define a lambda-style local redraw — in a real app this would be * a proper function taking your app struct. */ #define REDRAW() do { \ sk_fill(&p, SK_BG, 0, 0, WIN_W, WIN_H); \ \ /* Accent bar at top */ \ sk_fill(&p, SK_ACCENT, 0, 0, WIN_W, 3); \ \ /* Centred heading */ \ const char *title = "Hello, OrionOS"; \ int tw = sk_textw(&app, app.font_hdr, title); \ sk_text(&p, app.font_hdr, SK_TEXT_HDR, \ (WIN_W - tw) / 2, sk_baseline(app.font_hdr, 60, 32), title); \ \ /* Subtitle */ \ const char *sub = "A SkyKit native application"; \ int sw = sk_textw(&app, app.font_ui, sub); \ sk_text(&p, app.font_ui, SK_TEXT_DIM, \ (WIN_W - sw) / 2, sk_baseline(app.font_ui, 100, 24), sub); \ \ /* Click counter button */ \ SKBtn btn = { (WIN_W - 160) / 2, 160, 160, 36, "Click me", 1 }; \ sk_draw_btn(&p, &btn, 0); \ \ /* Counter label */ \ char cnt[64]; snprintf(cnt, sizeof(cnt), "Clicked %d time%s", clicks, clicks==1?"":"s"); \ int cw = sk_textw(&app, app.font_ui, cnt); \ sk_text(&p, app.font_ui, SK_TEXT, (WIN_W - cw) / 2, \ sk_baseline(app.font_ui, 215, 24), cnt); \ \ /* Hint */ \ const char *hint = "Press Q or Esc to quit"; \ int hw = sk_textw(&app, app.font_sm, hint); \ sk_text(&p, app.font_sm, SK_TEXT_DIM, (WIN_W - hw) / 2, \ sk_baseline(app.font_sm, WIN_H - 36, 24), hint); \ \ /* Blit to window */ \ XCopyArea(app.dpy, buf, win, gc, 0, 0, WIN_W, WIN_H, 0, 0); \ XFlush(app.dpy); \ } while (0) REDRAW(); /* ── Event loop ──────────────────────────────────────── */ int running = 1; while (running) { XEvent ev; XNextEvent(app.dpy, &ev); switch (ev.type) { case Expose: if (ev.xexpose.count == 0) REDRAW(); break; case KeyPress: { KeySym ks = XLookupKeysym(&ev.xkey, 0); if (ks == XK_q || ks == XK_Q || ks == XK_Escape) running = 0; break; } case ButtonPress: if (ev.xbutton.button == Button1) { /* check if inside the button */ int bx = (WIN_W - 160) / 2, by = 160; if (sk_in_rect(ev.xbutton.x, ev.xbutton.y, bx, by, 160, 36)) { clicks++; REDRAW(); } } break; case ClientMessage: if ((Atom)ev.xclient.data.l[0] == wm_del) running = 0; break; } } #undef REDRAW sk_app_free(&app); XFreePixmap(app.dpy, buf); XFreeGC(app.dpy, gc); XDestroyWindow(app.dpy, win); XCloseDisplay(app.dpy); return 0; }