Mercurial > x11calc
comparison main.cpp @ 0:12567e0a7670 default tip
initial commit
| author | Yasuri <yasuri@charliesmp.net> |
|---|---|
| date | Sun, 04 Oct 2026 12:56:43 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:12567e0a7670 |
|---|---|
| 1 #include <iostream> | |
| 2 #include <stdexcept> | |
| 3 #include <vector> | |
| 4 #include <string> | |
| 5 #include <sstream> | |
| 6 #include <cstring> | |
| 7 #include <unistd.h> | |
| 8 #include <X11/Xlib.h> | |
| 9 #include <X11/Xft/Xft.h> | |
| 10 #include <fontconfig/fontconfig.h> | |
| 11 #include <X11/keysym.h> | |
| 12 #include "calculate.h" | |
| 13 #include "x11.h" | |
| 14 | |
| 15 extern "C" { | |
| 16 #include "drw.h" | |
| 17 } | |
| 18 #include "config.h" | |
| 19 | |
| 20 struct Button { int x, y, w, h; std::string label; }; | |
| 21 | |
| 22 std::vector<Button> makeButtons() { | |
| 23 std::vector<Button> b; | |
| 24 for (int r = 0; r < 4; r++) | |
| 25 for (int c = 0; c < 4; c++) | |
| 26 b.push_back({gridX + c*(btnW+gap), gridY+ r*(btnH+gap), btnW, btnH, labels[r][c]}); | |
| 27 return b; | |
| 28 } | |
| 29 | |
| 30 void redraw(Drw* drw, Clr* btnScheme, Clr* dispScheme, | |
| 31 const std::vector<Button>& btns, const std::string& input) { | |
| 32 // display area (also paints the pixmap's background) | |
| 33 drw_setscheme(drw, dispScheme); | |
| 34 drw_rect(drw, 0, 0, 500, 500, 1, 1); | |
| 35 drw_text(drw, 10, 10, 480, 70, 10, input.c_str(), 0); | |
| 36 | |
| 37 // buttons | |
| 38 drw_setscheme(drw, btnScheme); | |
| 39 for (const auto& b : btns) { | |
| 40 unsigned int tw = drw_fontset_getwidth(drw, b.label.c_str()); | |
| 41 int lpad = (b.w - (int)tw) / 2; | |
| 42 drw_text(drw, b.x, b.y, b.w, b.h, lpad, b.label.c_str(), 0); | |
| 43 } | |
| 44 } | |
| 45 | |
| 46 int main() { | |
| 47 Display *dpy = displayopen(); | |
| 48 int screen = DefaultScreen(dpy); | |
| 49 Window root = RootWindow(dpy, screen); | |
| 50 Window win = XCreateSimpleWindow(dpy, root, 0, 0, 500, 500, 1, 0xFFFFFF, 0x000000); | |
| 51 XStoreName(dpy, win, "Calculator"); | |
| 52 XSelectInput(dpy, win, ExposureMask | KeyPressMask | ButtonPressMask); | |
| 53 XMapWindow(dpy, win); | |
| 54 | |
| 55 Atom wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False); | |
| 56 XSetWMProtocols(dpy, win, &wmDelete, 1); | |
| 57 | |
| 58 Drw* drw = drw_create(dpy, screen, root, 500, 500); | |
| 59 if (!drw) { std::cerr << "drw_create failed\n"; return 1; } | |
| 60 | |
| 61 if (!drw_fontset_create(drw, fonts, 1)) { | |
| 62 std::cerr << "font load failed\n"; | |
| 63 return 1; | |
| 64 } | |
| 65 | |
| 66 Clr* btnScheme = drw_scm_create(drw, btnColors, 3); | |
| 67 Clr* dispScheme = drw_scm_create(drw, dispColors, 3); | |
| 68 | |
| 69 std::vector<Button> btns = makeButtons(); | |
| 70 std::string input; | |
| 71 XEvent ev; | |
| 72 bool running = true; | |
| 73 | |
| 74 while (running) { | |
| 75 XNextEvent(dpy, &ev); | |
| 76 switch (ev.type) { | |
| 77 case ClientMessage: | |
| 78 if ((Atom)ev.xclient.data.l[0] == wmDelete) running = false; | |
| 79 break; | |
| 80 case Expose: | |
| 81 if (ev.xexpose.count == 0) { | |
| 82 redraw(drw, btnScheme, dispScheme, btns, input); | |
| 83 drw_map(drw, win, 0, 0, winW, winH); | |
| 84 } | |
| 85 break; | |
| 86 case KeyPress: { | |
| 87 KeySym k = XLookupKeysym(&ev.xkey, 0); | |
| 88 if (k == XK_q) running = false; | |
| 89 break; | |
| 90 } | |
| 91 case ButtonPress: | |
| 92 if (ev.xbutton.button != Button1) break; | |
| 93 for (const auto& b : btns) { | |
| 94 bool hit = ev.xbutton.x >= b.x && ev.xbutton.x < b.x + b.w && | |
| 95 ev.xbutton.y >= b.y && ev.xbutton.y < b.y + b.h; | |
| 96 if (!hit) continue; | |
| 97 | |
| 98 if (b.label == "=") { | |
| 99 size_t pos = input.find_first_of("+-*/", 1); | |
| 100 if (pos != std::string::npos) { | |
| 101 try { | |
| 102 double x = std::stod(input.substr(0, pos)); | |
| 103 double y = std::stod(input.substr(pos + 1)); | |
| 104 char op = input[pos]; | |
| 105 std::ostringstream ss; | |
| 106 ss << calculate(x, y, op); | |
| 107 input = ss.str(); | |
| 108 } catch (const std::exception& e) { | |
| 109 input = e.what(); | |
| 110 } | |
| 111 } | |
| 112 } else if (b.label == "C") { | |
| 113 input.clear(); | |
| 114 } else { | |
| 115 input += b.label; | |
| 116 } | |
| 117 XClearArea(dpy, win, 0, 0, 0, 0, True); | |
| 118 break; | |
| 119 } | |
| 120 break; | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 drw_free(drw); | |
| 125 XCloseDisplay(dpy); | |
| 126 } |
