commit 9d6fd550baf98a7be09ae4eaf02d4ead4ede58da Author: Joseph Ferano Date: Mon Aug 15 18:02:48 2022 +0700 X11 window with basic writing and input diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7982875 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.idea/ +/bt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..53acf48 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +P=bt +OBJECTS= +CFLAGS=-g -Wall -Wextra -pedantic -O0 +LDLIBS= +CC=gcc +RM=rm -vf + +bt: clean + $(CC) $(CFLAGS) -lX11 $(P).c -o $(P) + +clean: + $(RM) $(P) + +run:bt + ./$(P) + +all:$(P) diff --git a/bt.c b/bt.c new file mode 100644 index 0000000..28990d4 --- /dev/null +++ b/bt.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// PTY +int master; +int slave; + +// X11 +Display *display; +int screen; +Window win; +GC gc; +int x11fd; + +// Scrollback +char *scrollback; + +void init_x(void) { + unsigned long black,white; + display = XOpenDisplay((char *) 0); + screen = DefaultScreen(display); + black = BlackPixel(display, screen); + white = WhitePixel(display, screen); + + win = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, 500, 800, 5, white, black); + + XSetStandardProperties(display, win, "The window", "Hello", None, NULL, 0, NULL); + XSelectInput(display, win, ExposureMask|KeyPressMask); + gc = XCreateGC(display, win, 0, 0); + XSetBackground(display, gc, white); + XSetForeground(display, gc, black); + x11fd = ConnectionNumber(display); + XClearWindow(display, win); + XMapRaised(display, win); +} + +void close_x(void) { + XFreeGC(display, gc); + XDestroyWindow(display, win); + XCloseDisplay(display); + exit(0); +} + +void spawn(void) { + openpty(&master, &slave, NULL, NULL, NULL); + pid_t p = fork(); + if (p == 0) { + close(master); + + setsid(); + ioctl(slave, TIOCSCTTY, NULL); + dup2(slave, 0); + dup2(slave, 1); + dup2(slave, 2); + + close(slave); + + execle("/bin/dash", "-/bin/dash", (char *)NULL, (char *[]){ "TERM=dumb", NULL }); + exit(0); + } else { + close(slave); + } +} + +void update(void) { + XEvent event; + KeySym key; + char buf[1]; + char x11inputbuf[255]; + fd_set readable; + /* char tmp[512]; */ + scrollback = malloc(2048); + scrollback[0] = '\0'; + int sbcount = 0; + int maxfd = master > x11fd ? master : x11fd; + + for (;;) { + FD_ZERO(&readable); + FD_SET(master, &readable); + FD_SET(x11fd, &readable); + select(maxfd + 1, &readable, NULL, NULL, NULL); + if (FD_ISSET(master, &readable)) { + read(master, buf, 1); + scrollback[sbcount++] = *buf; + scrollback[sbcount] = '\0'; + XClearWindow(display, win); + char *curr = scrollback; + while (*curr) { + if (!iscntrl(*curr)) { + XSetForeground(display, gc, 255); + XDrawString(display, win, gc, 10, 10, curr, sbcount); + } + curr++; + } + } + while (XPending(display)) { + XNextEvent(display, &event); + switch (event.type) { + // This gets called when the window is resized + case Expose: // Resized + XClearWindow(display, win); + break; + case KeyPress: + if (XLookupString(&event.xkey,x11inputbuf,255,&key,0) == 1) { + switch (x11inputbuf[0]) { + case 'q': + close_x(); + break; + default: + write(master, &x11inputbuf[0], 1); + } + } + break; + } + } + } +} + +int main(void) { + init_x(); + spawn(); + + update(); + return 0; +} +