From: Michael D. Lowis Date: Thu, 10 Aug 2017 18:36:43 +0000 (-0400) Subject: Added tctl.c first pass for controlling a session. Added property handling to x11... X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=23434073dedaadc0577052ef7d90496beac4bb03;p=projs%2Ftide.git Added tctl.c first pass for controlling a session. Added property handling to x11 module to identify tide windows and register them with the root window --- diff --git a/.gitignore b/.gitignore index 604d147..e924b78 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,4 @@ tests/pick hl-cpp pty tfetch +tserve diff --git a/Makefile b/Makefile index 48c7681..b40135c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ INCS = -Iinc/ -BINS = tide pick xcpd hl-cpp tfetch +BINS = tide tfetch tctl pick xcpd hl-cpp MAN1 = docs/tide.1 docs/pick.1 docs/picktag.1 docs/pickfile.1 LIBEDIT_OBJS = \ @@ -34,8 +34,7 @@ docs: clean: find . -name '*.[oad]' -delete find . \( -name '*.gcno' -o -name '*.gcda' \) -delete - $(RM) pick tide xcpd term tests/libedit hl-cpp - $(RM) $(TEST_BINS) + $(RM) $(BINS) $(TEST_BINS) install: all mkdir -p $(PREFIX)/bin @@ -43,6 +42,7 @@ install: all cp -f tfetch $(PREFIX)/bin cp -f tide $(PREFIX)/bin cp -f tide-hl.rb $(PREFIX)/bin + cp -f tctl $(PREFIX)/bin cp -f pick $(PREFIX)/bin cp -f xcpd $(PREFIX)/bin cp -f pickfile $(PREFIX)/bin @@ -53,6 +53,7 @@ uninstall: rm -f $(PREFIX)/bin/tfetch rm -f $(PREFIX)/bin/tide rm -f $(PREFIX)/bin/tide-hl.rb + rm -f $(PREFIX)/bin/tctl rm -f $(PREFIX)/bin/pick rm -f $(PREFIX)/bin/xcpd rm -f $(PREFIX)/bin/pickfile @@ -69,6 +70,7 @@ pick: pick.o libedit.a xcpd: xcpd.o libedit.a hl-cpp: hl-cpp.o libedit.a tfetch: tfetch.o +tctl: tctl.o libedit.a tests/libedit: tests/libedit.o tests/lib/buf.o tests/lib/utf8.o libedit.a tests/tide: tests/tide.o libedit.a tests/pick: tests/pick.o libedit.a diff --git a/TODO.md b/TODO.md index 0efafa6..cd3ae38 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,10 @@ Up Next: +* Implement tab completion +* Change status to current dir in pty mode. +* synchronize title with status contents. +* Implement server daemon for tracking open files * B2+B1 click executes command with selection as argument * right click to fetch file or line * Run commands in the background and don't block the main thread. diff --git a/inc/x11.h b/inc/x11.h index a22224b..3279b8c 100644 --- a/inc/x11.h +++ b/inc/x11.h @@ -147,5 +147,3 @@ void x11_draw_utf8(XFont font, int fg, int bg, int x, int y, char* str); bool x11_sel_get(int selid, void(*cbfn)(char*)); bool x11_sel_set(int selid, char* str); - - diff --git a/lib/x11.c b/lib/x11.c index bc8950a..c089a96 100644 --- a/lib/x11.c +++ b/lib/x11.c @@ -15,6 +15,7 @@ static struct XSel* selfetch(Atom atom); static void selclear(XEvent* evnt); static void selnotify(XEvent* evnt); static void selrequest(XEvent* evnt); +static void propnotify(XEvent* evnt); struct XFont { struct { @@ -42,7 +43,7 @@ static struct { unsigned depth; int screen; /* assume a single window for now. these are its attributes */ - Window window; + Window self; XftDraw* xft; Pixmap pixmap; int width; @@ -94,6 +95,7 @@ void x11_init(XConfig* cfg) { X.colormap = wa.colormap; X.screen = DefaultScreen(X.display); X.depth = DefaultDepth(X.display, X.screen); + /* initialize selection atoms */ for (int i = 0; i < (sizeof(Selections) / sizeof(Selections[0])); i++) Selections[i].atom = XInternAtom(X.display, Selections[i].name, 0); @@ -121,7 +123,7 @@ void x11_window(char* name, int width, int height) { X.height = height; XWindowAttributes wa; XGetWindowAttributes(X.display, X.root, &wa); - X.window = XCreateSimpleWindow(X.display, X.root, + X.self = XCreateSimpleWindow(X.display, X.root, (wa.width - X.width) / 2, (wa.height - X.height) /2, X.width, @@ -131,15 +133,16 @@ void x11_window(char* name, int width, int height) { /* register interest in the delete window message */ Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False); - XSetWMProtocols(X.display, X.window, &wmDeleteMessage, 1); + XSetWMProtocols(X.display, X.self, &wmDeleteMessage, 1); /* setup window attributes and events */ XSetWindowAttributes swa; swa.backing_store = WhenMapped; swa.bit_gravity = NorthWestGravity; - XChangeWindowAttributes(X.display, X.window, CWBackingStore|CWBitGravity, &swa); - XStoreName(X.display, X.window, name); - XSelectInput(X.display, X.window, + XChangeWindowAttributes(X.display, X.self, CWBackingStore|CWBitGravity, &swa); + XStoreName(X.display, X.self, name); + XSelectInput(X.display, X.root, PropertyChangeMask); + XSelectInput(X.display, X.self, StructureNotifyMask | ButtonPressMask | ButtonReleaseMask @@ -150,24 +153,30 @@ void x11_window(char* name, int width, int height) { /* set input methods */ if ((X.xim = XOpenIM(X.display, 0, 0, 0))) - X.xic = XCreateIC(X.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, X.window, XNFocusWindow, X.window, NULL); + X.xic = XCreateIC(X.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, X.self, XNFocusWindow, X.self, NULL); /* initialize pixmap and drawing context */ - X.pixmap = XCreatePixmap(X.display, X.window, width, height, X.depth); + X.pixmap = XCreatePixmap(X.display, X.self, width, height, X.depth); X.xft = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap); /* initialize the graphics context */ XGCValues gcv; gcv.foreground = WhitePixel(X.display, X.screen); gcv.graphics_exposures = False; - X.gc = XCreateGC(X.display, X.window, GCForeground|GCGraphicsExposures, &gcv); + X.gc = XCreateGC(X.display, X.self, GCForeground|GCGraphicsExposures, &gcv); + + /* Create and updtate tide-specific properties */ + Atom prop = XInternAtom(X.display, "TIDE_WINDOWS", False); + XChangeProperty(X.display, X.root, prop, XA_WINDOW, 32, PropModeAppend, (unsigned char*)&X.self, 1); + prop = XInternAtom(X.display, "TIDE_COMM", False); + XChangeProperty(X.display, X.self, prop, XA_STRING, 8, PropModeReplace, "", 0); } void x11_dialog(char* name, int height, int width) { x11_window(name, height, width); Atom WindowType = XInternAtom(X.display, "_NET_WM_WINDOW_TYPE", False); Atom DialogType = XInternAtom(X.display, "_NET_WM_WINDOW_TYPE_DIALOG", False); - XChangeProperty(X.display, X.window, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1); + XChangeProperty(X.display, X.self, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1); } void x11_show(void) { @@ -176,8 +185,8 @@ void x11_show(void) { ce.type = ConfigureNotify; ce.width = X.width; ce.height = X.height; - XSendEvent(X.display, X.window, False, StructureNotifyMask, (XEvent *)&ce); - XMapWindow(X.display, X.window); + XSendEvent(X.display, X.self, False, StructureNotifyMask, (XEvent *)&ce); + XMapWindow(X.display, X.self); } bool x11_running(void) { @@ -186,7 +195,7 @@ bool x11_running(void) { void x11_flip(void) { Config->redraw(X.width, X.height); - XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0); + XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0); x11_flush(); } @@ -327,6 +336,7 @@ void x11_handle_event(XEvent* e) { case SelectionClear: selclear(e); break; case SelectionNotify: selnotify(e); break; case SelectionRequest: selrequest(e); break; + case PropertyNotify: propnotify(e); break; case ClientMessage: if (e->xclient.data.l[0] == wmDeleteMessage) Config->shutdown(); @@ -335,7 +345,7 @@ void x11_handle_event(XEvent* e) { if (e->xconfigure.width != X.width || e->xconfigure.height != X.height) { X.width = e->xconfigure.width; X.height = e->xconfigure.height; - X.pixmap = XCreatePixmap(X.display, X.window, X.width, X.height, X.depth); + X.pixmap = XCreatePixmap(X.display, X.self, X.width, X.height, X.depth); X.xft = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap); } break; @@ -349,7 +359,7 @@ int x11_events_queued(void) { void x11_events_take(void) { XEvent e; int nevents; - XGetMotionEvents(X.display, X.window, CurrentTime, CurrentTime, &nevents); + XGetMotionEvents(X.display, X.self, CurrentTime, CurrentTime, &nevents); while (XPending(X.display)) { XNextEvent(X.display, &e); if (!XFilterEvent(&e, None)) @@ -358,12 +368,12 @@ void x11_events_take(void) { } void x11_mouse_set(int x, int y) { - XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y); + XWarpPointer(X.display, X.self, X.self, 0, 0, X.width, X.height, x, y); } void x11_mouse_get(int* ptrx, int* ptry) { Window xw; int x; unsigned int ux; - XQueryPointer(X.display, X.window, &xw, &xw, &x, &x, ptrx, ptry, &ux); + XQueryPointer(X.display, X.self, &xw, &xw, &x, &x, ptrx, ptry, &ux); } XFont x11_font_load(char* name) { @@ -522,7 +532,6 @@ void x11_draw_utf8(XFont fnt, int fg, int bg, int x, int y, char* str) { /* Selection Handling *****************************************************************************/ - static char* readprop(Display* disp, Window win, Atom prop) { Atom type; int format; @@ -562,7 +571,7 @@ static void selnotify(XEvent* evnt) { if (evnt->xselection.property == None) return; struct XSel* sel = selfetch( evnt->xselection.selection ); - char* propdata = readprop(X.display, X.window, sel->atom); + char* propdata = readprop(X.display, X.self, sel->atom); if (evnt->xselection.target == SelTarget) { void(*cbfn)(char*) = sel->callback; sel->callback = NULL; @@ -608,11 +617,11 @@ bool x11_sel_get(int selid, void(*cbfn)(char*)) { struct XSel* sel = &(Selections[selid]); if (sel->callback) return false; Window owner = XGetSelectionOwner(X.display, sel->atom); - if (owner == X.window) { + if (owner == X.self) { cbfn(sel->text); } else if (owner != None){ sel->callback = cbfn; - XConvertSelection(X.display, sel->atom, SelTarget, sel->atom, X.window, CurrentTime); + XConvertSelection(X.display, sel->atom, SelTarget, sel->atom, X.self, CurrentTime); } return true; } @@ -624,7 +633,12 @@ bool x11_sel_set(int selid, char* str) { return false; } else { sel->text = str; - XSetSelectionOwner(X.display, sel->atom, X.window, CurrentTime); + XSetSelectionOwner(X.display, sel->atom, X.self, CurrentTime); return true; } } + +/* Tide Server Communication + *****************************************************************************/ +static void propnotify(XEvent* evnt) { +} diff --git a/tctl.c b/tctl.c new file mode 100644 index 0000000..00cd196 --- /dev/null +++ b/tctl.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include + +struct { + Display* display; + Window root; + Window self; +} X; + +static void* prop_get(Window win, char* propname, Atom type, unsigned long* nitems); +static void prop_set(Window win, char* propname, Atom type, int format, void* items, unsigned long nitems); + +/* Main Routine + ******************************************************************************/ +int main(int argc, char** argv) { + if (!(X.display = XOpenDisplay(0))) + die("could not open display"); + X.root = DefaultRootWindow(X.display); + X.self = XCreateSimpleWindow(X.display, X.root, 0, 0, 1, 1, 0, 0, 0); + + XGrabServer(X.display); + unsigned long nwindows = 0; + Window* windows = prop_get(X.root, "TIDE_WINDOWS", XA_WINDOW, &nwindows); + printf("Windows: %lu\n", nwindows); + XUngrabServer(X.display); + + return 0; +} + +static void* prop_get(Window win, char* propname, Atom type, unsigned long* nitems) { + Atom rtype, prop = XInternAtom(X.display, propname, False); + unsigned long rformat = 0, nleft = 0; + unsigned char* data = NULL; + XGetWindowProperty(X.display, win, prop, 0, -1, False, type, &rtype, + (int*)&rformat, nitems, &nleft, &data); + if (rtype != type) + data = NULL, *nitems = 0; + return data; +} + +static void prop_set(Window win, char* propname, Atom type, int format, void* items, unsigned long nitems) { + Atom prop = XInternAtom(X.display, propname, False); + XChangeProperty(X.display, win, prop, type, format, PropModeReplace, items, (int)nitems); +} diff --git a/tide.c b/tide.c index 0fb1b69..915f5e4 100644 --- a/tide.c +++ b/tide.c @@ -232,6 +232,7 @@ void onmouseright(WinRegion id, bool pressed, size_t row, size_t col) { /* Keyboard Handling ******************************************************************************/ static void saveas(char* arg) { + //win_saveas(stringdup(arg)); if (arg) { char* path = win_buf(EDIT)->path; win_buf(EDIT)->path = stringdup(arg); @@ -573,9 +574,11 @@ void edit_relative(char* path) { else strconcat(currpath, fname, 0); chdir(currdir); + //win_open(currpath, ondiagmsg); view_init(win_view(EDIT), currpath, ondiagmsg); } else { chdir(origdir); + //win_open(path, ondiagmsg); view_init(win_view(EDIT), path, ondiagmsg); }