]> git.mdlowis.com Git - projs/tide.git/commitdiff
tctl can now open new editors as well as activate existing ones
authorMichael D. Lowis <mike@mdlowis.com>
Sun, 13 Aug 2017 00:21:52 +0000 (20:21 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sun, 13 Aug 2017 00:21:52 +0000 (20:21 -0400)
lib/win.c
tctl.c

index 31f6b7870e15dd2c4e0add6f2fb56f567ab3aef9..9951b49a791a2d85b6b32399aca362509eee89ea 100644 (file)
--- a/lib/win.c
+++ b/lib/win.c
@@ -66,10 +66,9 @@ static void win_update(int xfd, void* data) {
 }
 
 static void set_path_prop(char* path) {
-    char *newpath = calloc(1, PATH_MAX+1),
-         *abspath = realpath(path, newpath);
-    x11_prop_set("TIDE_FILE", abspath);
-    free(newpath);
+    char *abspath = realpath(path, NULL);
+    x11_prop_set("TIDE_FILE", (!abspath ? "" : abspath));
+    free(abspath);
 }
 
 void win_load(char* path) {
diff --git a/tctl.c b/tctl.c
index 99c59ebe2b3c22a519e767c2be5ff18c8aed8520..fa84f810a6ab5ee91a25b9283d7f83f03c91d968 100644 (file)
--- a/tctl.c
+++ b/tctl.c
@@ -10,15 +10,20 @@ struct {
     Display* display;
     Window root;
     Window self;
+    int error;
 } X;
 
+size_t WinCount;
+Window* Windows;
+char**  WinFiles;
+
+static void get_windows(Window** wins, char*** files, size_t* nwins);
+static int error_handler(Display* disp, XErrorEvent* ev);
 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);
-
-char* abspath(char* path) {
-    char* newpath = calloc(1, PATH_MAX+1);
-    return realpath(path, newpath);
-}
+static void edit(char* path);
+static Window win_byfile(char* path);
+static void focus_window(Window w);
 
 /* Main Routine
  ******************************************************************************/
@@ -27,17 +32,54 @@ int main(int argc, char** argv) {
         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);
+    XSetErrorHandler(error_handler);
+    get_windows(&Windows, &WinFiles, &WinCount);
 
     for (int i = 1; i < argc; i++) {
-        printf("abspath: '%s'\n", abspath(argv[i]));
+        bool last = (i == argc-1);
+        char* path = realpath(argv[i], NULL);
+        if (!path) path = argv[i];
+        Window win = win_byfile(path);
+        if (!win)
+            edit(path);
+        else if (last)
+            focus_window(win);
     }
+       XFlush(X.display);
+    return 0;
+}
 
+static void get_windows(Window** wins, char*** files, size_t* nwins) {
+    XGrabServer(X.display);
+    unsigned long nwindows = 0, nactive = 0, nstrings = 0;
+    Window *windows = prop_get(X.root, "TIDE_WINDOWS", XA_WINDOW, &nwindows);
+    Window *active  = calloc(nwindows, sizeof(Window));
+    char   **wfiles  = calloc(nwindows, sizeof(char*));
+    Atom xa_comm = XInternAtom(X.display, "TIDE_COMM", False);
+    for (int i = 0; i < nwindows; i++) {
+        X.error = 0;
+        int nprops;
+        Atom* props = XListProperties(X.display, windows[i], &nprops);
+        if (!props || X.error) continue;
+        for (int x = 0; x < nprops; x++) {
+            if (props[x] == xa_comm) {
+                active[nactive] = windows[i];
+                wfiles[nactive] = prop_get(windows[i], "TIDE_FILE", XA_STRING, &nstrings);
+                nactive++;
+                break;
+            }
+        }
+        XFree(props);
+    }
+    prop_set(X.root, "TIDE_WINDOWS", XA_WINDOW, 32, active, nactive);
+    XSync(X.display, False);
+    XUngrabServer(X.display);
+    XFree(windows);
+    *wins  = active, *files = wfiles, *nwins = nactive;
+}
+
+static int error_handler(Display* disp, XErrorEvent* ev) {
+    X.error = ev->error_code;
     return 0;
 }
 
@@ -56,3 +98,28 @@ static void prop_set(Window win, char* propname, Atom type, int format, void* it
     Atom prop = XInternAtom(X.display, propname, False);
     XChangeProperty(X.display, win, prop, type, format, PropModeReplace, items, (int)nitems);
 }
+
+static void edit(char* path) {
+    if (fork() == 0)
+       execv("tide", (char*[]){ "tide", path, NULL });
+}
+
+static Window win_byfile(char* path) {
+    for (int i = 0; i < WinCount; i++)
+        if (WinFiles[i] && !strcmp(path, WinFiles[i]))
+            return Windows[i];
+    return (Window)0;
+}
+
+static void focus_window(Window w) {
+       XEvent ev = {0};
+       ev.xclient.type = ClientMessage;
+    ev.xclient.send_event = True;
+    ev.xclient.message_type = XInternAtom(X.display, "_NET_ACTIVE_WINDOW", False);
+       ev.xclient.window = w;
+       ev.xclient.format = 32;
+    long mask = SubstructureRedirectMask | SubstructureNotifyMask;
+       XSendEvent(X.display, X.root, False, mask, &ev);
+    XMapRaised(X.display, w);
+    XFlush(X.display);
+}