master
xtr.c
1#include <X11/Xlib.h>
2#include <X11/keysym.h>
3#include <xkbcommon/xkbcommon.h>
4
5#include <stdbool.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10#include <getopt.h>
11
12#include "config.h"
13
14int main(int ac, char **av) {
15 int wi = 350, hi = 75, x = 0, y = 0;
16
17 char path[128];
18 snprintf(path, sizeof path, "%s/%s", getenv("HOME"), ".xlrc");
19
20 char *fnt = NULL;
21
22 int opt;
23 while ((opt = getopt(ac, av, "f:h ")) != -1) {
24 switch (opt) {
25 case 'f':
26 fnt = optarg;
27 break;
28 case 'h':
29 fprintf(stderr, "usage: %s [-f fontname]\nusage: %s [-h]\nusage: %s\n",
30 av[0], av[0], av[0]);
31 return 0;
32 break;
33 case ':':
34 fprintf(stderr, "-%c needs a argument!\n", optopt);
35 return 1;
36 break;
37 case '?':
38 fprintf(stderr, "unknown flag: -%c\n", optopt);
39 return 1;
40 break;
41 }
42 }
43
44 Display *d = XOpenDisplay(NULL);
45 if (!d) {
46 fprintf(stderr, "couldnt open display\n");
47 return 1;
48 }
49
50 int s = DefaultScreen(d);
51 int swi = DisplayWidth(d, s);
52 int shi = DisplayHeight(d, s);
53
54 Window r = DefaultRootWindow(d);
55 Window w_r;
56 unsigned int m_r;
57 int d1, d2;
58
59 if (XQueryPointer(d, r, &w_r, &w_r, &x, &y, &d1, &d2, &m_r)) {
60 }
61
62 XColor col[6];
63 for (size_t c = 0; cols[c] != NULL; c++) {
64 XParseColor(d, DefaultColormap(d, s), cols[c], &col[c]);
65 XAllocColor(d, DefaultColormap(d, s), &col[c]);
66 }
67
68 Window w = XCreateSimpleWindow(d, RootWindow(d, s), (swi / 2) - (wi / 2),
69 (shi / 2) - (hi / 2), wi, hi, 1, col[0].pixel,
70 WhitePixel(d, s));
71 XStoreName(d, w, "xlnd");
72 XSelectInput(d, w, ExposureMask | KeyPressMask | KeyReleaseMask);
73 /*
74 * dont make it a regular window
75 * kinda like rofi or layer-shell
76 */
77 XSetWindowAttributes at;
78 at.override_redirect = True;
79 XChangeWindowAttributes(d, w, CWOverrideRedirect, &at);
80
81 XMapWindow(d, w);
82 XMapRaised(d, w);
83 XSetInputFocus(d, w, RevertToPointerRoot, CurrentTime);
84 XGrabKeyboard(d, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
85 XGrabPointer(d, w, True, ButtonPressMask | PointerMotionMask, GrabModeAsync,
86 GrabModeAsync, None, None, CurrentTime);
87
88 GC gc = XCreateGC(d, w, 0, NULL);
89 XSetForeground(d, gc, WhitePixel(d, s));
90 XFillRectangle(d, w, gc, 0, 0, wi, hi);
91 XSetForeground(d, gc, BlackPixel(d, s));
92
93 XFontStruct *font = XLoadQueryFont(d, fnt ? fnt : "fixed");
94 if (!font)
95 font = XLoadQueryFont(d, "fixed");
96 XSetFont(d, gc, font->fid);
97
98 bool end = false;
99 bool Nend = false;
100 int cmd_end = 0;
101 char cmd[512];
102 size_t idx = 0;
103 for (int c = 0; c < 1023; c++) {
104 cmd[c] = '\0';
105 }
106
107 struct xkb_context *ctx;
108 struct xkb_keymap *keymap;
109 struct xkb_state *state;
110
111 ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
112
113 keymap = xkb_keymap_new_from_names(ctx, &(struct xkb_rule_names){0},
114 XKB_KEYMAP_COMPILE_NO_FLAGS);
115
116 state = xkb_state_new(keymap);
117
118 while (1) {
119 XEvent ev;
120 XNextEvent(d, &ev);
121
122 switch (ev.type) {
123 case Expose:
124 if (ev.xexpose.count != 0)
125 break;
126
127 int direction, as, des;
128 XCharStruct ov;
129 XTextExtents(font, cmd, strlen(cmd), &direction, &as, &des, &ov);
130
131 int Ndirection, Nas, Ndes;
132 XCharStruct Nov;
133 XTextExtents(font, cmd + cmd_end, strlen(cmd + cmd_end), &Ndirection,
134 &Nas, &Ndes, &Nov);
135
136 XSetForeground(d, gc, col[1].pixel);
137 XFillRectangle(d, w, gc, 0, 0, wi, hi);
138 XSetForeground(d, gc, col[2].pixel);
139 XFillRectangle(d, w, gc, 10, 30, wi - 20, hi - 30 - 10);
140
141 XSetForeground(d, gc, col[1].pixel);
142 XFillRectangle(d, w, gc, 10 + 1, 30 + 1, wi - 20 - (1 * 2),
143 hi - 30 - 10 - (1 * 2));
144 XSetForeground(d, gc, col[0].pixel);
145
146 char cmd_str[512 + 1];
147 strncpy(cmd_str, cmd, end ? cmd_end : strlen(cmd));
148 cmd_str[512] = '\0';
149 XDrawString(d, w, gc, 15 - 2, 30 + (as + des) + 2, cmd, strlen(cmd_str));
150
151 if (end) {
152 XDrawString(d, w, gc, 15 - 2, 30 + ((as + des) * 2), cmd + cmd_end,
153 strlen(cmd + cmd_end));
154 }
155
156 if (ov.width - 15 > (wi - 30 - 20) && !end) {
157 cmd_end = strlen(cmd);
158 printf("%d\n", cmd_end);
159 end = true;
160 }
161 if (Nov.width - 15 > (wi - 30 - 10) && end) {
162 Nend = true;
163 }
164
165 break;
166 case KeyPress: {
167 xkb_keycode_t xkb = ev.xkey.keycode;
168 xkb_state_update_key(state, xkb, XKB_KEY_DOWN);
169 KeySym k = XLookupKeysym(&ev.xkey, 0);
170
171 if (k == XK_Escape) {
172 goto q;
173 }
174 if (k == XK_Return) {
175 puts(cmd);
176 goto q;
177 }
178 if (k == XK_BackSpace) {
179 if (idx > 0) {
180 cmd[idx--] = ' ';
181 XClearArea(d, w, 0, 0, 0, 0, True);
182 }
183 break;
184 }
185
186 if (Nend) {
187 xkb_state_update_key(state, xkb, XKB_KEY_UP);
188 break;
189 }
190
191 char buf[32];
192
193 int l = xkb_state_key_get_utf8(state, xkb, buf, sizeof(buf));
194
195 if (l > 0) {
196 if (idx + l < sizeof(cmd)) {
197 cmd[idx++] = buf[0];
198 XClearArea(d, w, 0, 0, 0, 0, True);
199 }
200 }
201
202 break;
203 }
204 case KeyRelease: {
205 xkb_keycode_t xkb = ev.xkey.keycode;
206 xkb_state_update_key(state, xkb, XKB_KEY_UP);
207 break;
208 }
209 }
210 }
211
212q:
213 xkb_state_unref(state);
214 xkb_keymap_unref(keymap);
215 xkb_context_unref(ctx);
216 XFreeFont(d, font);
217 XUngrabKeyboard(d, CurrentTime);
218 XUngrabPointer(d, CurrentTime);
219 XFreeGC(d, gc);
220 XDestroyWindow(d, w);
221 XCloseDisplay(d);
222 return 0;
223}