]> git.mdlowis.com Git - projs/tide.git/commitdiff
added borders and color to windows and titlebar
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 31 May 2019 15:24:36 +0000 (11:24 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 31 May 2019 15:24:36 +0000 (11:24 -0400)
hulksmash.c [new file with mode: 0644]
src/anvil.c
testsed.sh [new file with mode: 0755]
view_rework.diff [new file with mode: 0644]

diff --git a/hulksmash.c b/hulksmash.c
new file mode 100644 (file)
index 0000000..777cc1d
--- /dev/null
@@ -0,0 +1,309 @@
+/*  (The MIT License)
+ *
+ * Copyright (c) 2014 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the 'Software'), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Link with libusb >= 1.0.0 (which uses the newer style api)
+ *
+ * gcc -Wall button.c -lusb-1.0.0 -I /usr/include/libusb-1.0/
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include <unistd.h>
+#include <signal.h>
+
+#include <libusb.h>
+
+static bool debug = false;
+
+#define DEBUG(_fmt, ...) if (debug) fprintf(stdout, "brb: " _fmt "\n", ## __VA_ARGS__)
+#define INFO(_fmt, ...) fprintf(stdout, "brb: "_fmt "\n", ## __VA_ARGS__)
+#define ERROR(_fmt, ...) fprintf(stderr, "brb: " _fmt "\n", ## __VA_ARGS__)
+
+typedef enum button_state {
+       BUTTON_STATE_ERROR = -1,        //!< Error occurred getting button state
+       BUTTON_STATE_UNKNOWN = 0,
+       BUTTON_STATE_LID_CLOSED = 0x15, //!< Button lid is closed
+       BUTTON_STATE_PRESSED = 0x16,    //!< Button is currently depressed (and lid is open)
+       BUTTON_STATE_LID_OPEN = 0x17    //!< Button lid is open
+} button_states_t;
+
+#define BRB_VID 0x1d34                 //!< Big Red Button Vendor ID
+#define BRB_PID 0x0008                 //!< Big Red Button Product ID
+#define BRB_POLL_INTERVAL 20000                //!< How long we wait in between polling the button
+
+static char const *progname;           //!< What the binary's called
+static bool should_exit = false;       //!< If true, break out of the poll loop.
+
+static bool kernel_was_attached;
+
+/** Find the device, and detach the kernel driver
+ *
+ */
+static struct libusb_device_handle *get_button_handle(void){
+       struct libusb_device_handle *handle = NULL;
+       int ret;
+
+       DEBUG("Attempting to open device (vendor 0x%04x, device 0x%04x)", BRB_VID, BRB_PID);
+       handle = libusb_open_device_with_vid_pid(NULL, BRB_VID, BRB_PID);
+       if (!handle) {
+               ERROR("Failed opening device descriptor (you may need to be root)...");
+               return NULL;
+       }
+
+       /* If the kernel driver is active, we need to detach it */
+       if (libusb_kernel_driver_active(handle, 0)) {
+               DEBUG("Kernel driver active, attempting to detach...");
+               ret = libusb_detach_kernel_driver(handle, 0);
+               if (ret < 0 ){
+                       ERROR("Can't detach kernel driver");
+                       return NULL;
+               }
+
+               kernel_was_attached = true;
+        }
+
+        return handle;
+}
+
+
+static int set_button_control(struct libusb_device_handle *handle)
+{
+       int ret;
+       uint8_t state[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
+
+       ret = libusb_control_transfer(handle, 0x21, 0x09, 0x00, 0x00, state, 8, 0);
+       if (ret < 0) {
+               ERROR("Error reading response %i", ret);
+               return -1;
+       }
+       if (ret == 0) {
+               ERROR("Device didn't send enough data");
+               return -1;
+       }
+
+       return 0;
+}
+
+/** Returns the current button state
+ *
+ */
+static button_states_t read_button_state(struct libusb_device_handle *handle) {
+
+       uint8_t data[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       int dev[8];
+       int ret;
+
+       ret = set_button_control(handle);
+       if (ret < 0) {
+               return -1;
+       }
+
+       /* Send 0x81 to the EP to retrieve the state */
+       ret = libusb_interrupt_transfer(handle, 0x81, data, 8, dev, 200);
+       if (ret < 0) {
+               ERROR("Error getting interrupt data");
+               return -1;
+       }
+
+//            printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+//                data[0],
+//                data[1],
+//                data[2],
+//                data[3],
+//                data[4],
+//                data[5],
+//                data[6],
+//                data[7]
+//            );
+
+       return (data[0] == 0x1A ? BUTTON_STATE_PRESSED : BUTTON_STATE_UNKNOWN);
+}
+
+void run_command(char const *cmd) {
+       int ret;
+
+       DEBUG("Running command: %s", cmd);
+       ret = system(cmd);
+       DEBUG("Command returned %i", ret);
+}
+
+/** Cleanup gracefully
+ *
+ */
+void exit_handler(int sig_num);        /* Prototype for signal */
+void exit_handler(int sig_num)
+{
+       signal(SIGINT, exit_handler);
+       should_exit = true;
+}
+
+static void usage(int status)
+{
+       FILE *output = status ? stderr : stdout;
+
+       fprintf(output, "Usage: %s [options]\n", progname);
+       fprintf(output, "  -P <microsends>   Polling interval\n");
+       fprintf(output, "  -o <command>      Command to execute when button lid is open.\n");
+       fprintf(output, "  -c <command>      Command to execute when button lid is closed.\n");
+       fprintf(output, "  -p <command>      Command to execute when button is pressed.\n");
+       fprintf(output, "  -r <command>      Command to execute when button is released.\n");
+       fprintf(output, "  -h                This help text.\n");
+       fprintf(output, "  -v                Turn on verbose output.\n");
+
+       exit(status);
+}
+
+/** Main program
+ *
+ */
+int main (int argc, char *argv[]) {
+       char c;
+
+       char const *cmd_lid_open = NULL;
+       char const *cmd_lid_closed = NULL;
+       char const *cmd_pressed = NULL;
+       char const *cmd_released = NULL;
+
+       int interval = BRB_POLL_INTERVAL;
+
+       struct libusb_device_handle *handle = NULL;
+       button_states_t then = BUTTON_STATE_UNKNOWN, now;
+
+       progname = argv[0];
+
+       while ((c = getopt(argc, argv, "P:o:c:p:r:hv")) != EOF) {
+               switch (c) {
+               case 'P':
+                       interval = atoi(optarg);
+                       break;
+
+               case 'o':
+                       cmd_lid_open = optarg;
+                       break;
+
+               case 'c':
+                       cmd_lid_closed = optarg;
+                       break;
+
+               case 'p':
+                       cmd_released = optarg;
+                       break;
+
+               case 'r':
+                       cmd_pressed = optarg;
+                       break;
+
+               case 'h':
+                       usage(0);
+                       break;
+
+               case 'v':
+                       debug = true;
+                       break;
+               }
+       }
+
+       /* Setup a signal handler, so we can cleanup gracefully */
+       signal(SIGINT, exit_handler);
+
+       /* Initialise libusb (with the default context) */
+       libusb_init(NULL);
+
+#if defined(LIBUSB_LOG_LEVEL_DEBUG) && defined(LIBUSB_LOG_LEVEL_ERROR)
+       /* All the debugging messages !*/
+       if (debug) {
+               libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_DEBUG);
+       /* We still want to know about errors (helps with debugging) */
+       } else {
+               libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_ERROR);
+       }
+#endif
+
+       /* If we can't get the handle, exit... */
+       handle = get_button_handle();
+       if (!handle) exit(1);
+
+       if (read_button_state(handle) == BUTTON_STATE_ERROR) goto finish;
+
+       /* Loop, polling the device to get it's status */
+       while (should_exit != true) {
+               now = read_button_state(handle);
+               if (now == BUTTON_STATE_ERROR) goto skip;
+               if (then == now) goto skip;
+
+               if (then == BUTTON_STATE_PRESSED) {
+                       /* Run the released action */
+                       INFO("RELEASED");
+                       if (cmd_released) run_command(cmd_released);
+
+                       /* Weird but I guess it could happen... */
+                       if (now == BUTTON_STATE_LID_CLOSED) goto closed;
+                       goto next;
+               }
+
+               switch (now) {
+               case BUTTON_STATE_PRESSED:
+                       /* Run the pressed action */
+                       INFO("PRESSED");
+                       if (cmd_pressed) run_command(cmd_pressed);
+                       break;
+
+               case BUTTON_STATE_LID_OPEN:
+                       /* Run the lid open action */
+                       INFO("LID_OPEN");
+                       if (cmd_lid_open) run_command(cmd_lid_open);
+                       break;
+
+               case BUTTON_STATE_LID_CLOSED:
+               closed:
+                       /* Run the closed action */
+                       INFO("LID_CLOSED");
+                       if (cmd_lid_closed) run_command(cmd_lid_closed);
+                       break;
+
+               default:
+                       goto skip;
+               }
+
+       next:
+               then = now;
+       skip:
+               usleep(interval);
+       }
+
+finish:
+       DEBUG("Exiting...");
+
+       fflush(stdout);
+       fflush(stderr);
+
+//     if (kernel_was_attached) {
+//             libusb_attach_kernel_handle(ghandle, 0);
+//     }
+
+       libusb_close(handle);
+
+       exit(0);
+}
index 0ee12a9f58264ab5be934cc5d83ba7acd47e865a..a8af2eb9063b8fb2bced73fce7fd4927f6559921 100644 (file)
@@ -22,6 +22,11 @@ typedef struct Client {
 XConf X = {0};
 Client* Clients = NULL;
 
+/* configuration */
+uint32_t BorderWidth = 1;
+uint32_t BorderColor = 0x000077;
+uint32_t BackgroundColor = 0x000077;
+
 /* Utility Functions
  *****************************************************************************/
 void die(char* errstr) {
@@ -53,13 +58,11 @@ void client_add(XConf* x, Window win) {
     XGetWindowAttributes(x->display, win, &attr);
     c->x = attr.x, c->y = attr.y;
     c->w = attr.width, c->h = attr.height;
-    XSetWindowAttributes pattr = {0};
-    pattr.override_redirect = True;
-    c->frame = XCreateWindow(
-        x->display, x->root, 0, 0, 1, 1, 0,
-        x->depth, CopyFromParent, x->visual,
-        CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWEventMask, &pattr);
+    c->frame = XCreateSimpleWindow(x->display, x->root, 0, 0, 1, 1,
+        BorderWidth, BorderColor, BackgroundColor);
     c->xft = XftDrawCreate(x->display, (Drawable) c->frame, x->visual, x->colormap);
+    XSetWindowAttributes pattr = { .override_redirect = True };
+    XChangeWindowAttributes(x->display, c->frame, CWOverrideRedirect, &pattr);
 
     /* setup event handling on both windows */
     XSelectInput(x->display, c->frame,
@@ -68,7 +71,8 @@ void client_add(XConf* x, Window win) {
         EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
 
     /* position the window and frame */
-    XSetWindowBorderWidth(x->display, c->win, 0);
+    XSetWindowBorder(x->display, c->win, BorderColor);
+    XSetWindowBorderWidth(x->display, c->win, BorderWidth);
     XMoveResizeWindow(x->display, c->frame, 100, 100 - x->font->height, c->w, x->font->height);
     XMoveResizeWindow(x->display, c->win, 100, 100, c->w, c->h);
 
diff --git a/testsed.sh b/testsed.sh
new file mode 100755 (executable)
index 0000000..a1c196e
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+gcc -O2 msed.c
+cat sqlite2 | time ./a.out "$1" > /dev/null
+cat sqlite2 | time sed "$1" > /dev/null
diff --git a/view_rework.diff b/view_rework.diff
new file mode 100644 (file)
index 0000000..48aca40
--- /dev/null
@@ -0,0 +1,278 @@
+diff --git a/TODO.md b/TODO.md
+index fcfe8a5..475e3bb 100644
+--- a/TODO.md
++++ b/TODO.md
+@@ -37,3 +37,14 @@ Maybe think about addressing these later:
+ * Find shortcut should select previous word if current char is newline
+ * implement command diffing logic to optimize the undo/redo log
+ * right click negative numbers should jump to that many lines from the end of file
++
++
++1P                  Move the cursor
++1P 1R 1P            Select clicked on word
++1P 1R 1P 1R 1P      Select whole non whitespace thing
++2P 2R               Execute clicked word
++2P 1P 2R            Execute clicked word with argument
++3P 3R               Fetch clicked word
++3P 1P 3R            ?? Go to definition ??
++1P 2P 2R            Cut the selected text
++1P 3P 3R            Paste the selection
+diff --git a/inc/edit.h b/inc/edit.h
+index b9e2881..01fdcee 100644
+--- a/inc/edit.h
++++ b/inc/edit.h
+@@ -127,7 +127,8 @@ Row* view_getrow(View* view, size_t row);
+ void view_byrune(View* view, int move, bool extsel);
+ void view_byword(View* view, int move, bool extsel);
+ void view_byline(View* view, int move, bool extsel);
+-char* view_fetch(View* view, size_t row, size_t col, bool (*isword)(Rune));
++size_t view_getoffset(View* view, size_t row, size_t col);
++char* view_fetch(View* view, size_t off, bool (*isword)(Rune));
+ bool view_findstr(View* view, int dir, char* str);
+ void view_insert(View* view, Rune rune);
+ void view_delete(View* view, int dir, bool byword);
+@@ -149,10 +150,10 @@ void view_scrollpage(View* view, int move);
+ void view_setln(View* view, size_t line);
+ size_t view_selsize(View* view);
+ void view_selprev(View* view);
+-void view_setcursor(View* view, size_t row, size_t col, bool extsel);
++void view_setcursor(View* view, size_t off, bool extsel);
+ void view_selextend(View* view, size_t row, size_t col);
+-void view_selword(View* view, size_t row, size_t col);
+-void view_select(View* view, size_t row, size_t col);
++void view_selword(View* view, size_t off);
++void view_select(View* view, size_t off);
+ void view_jumpto(View* view, bool extsel, size_t off);
+ void view_scrollto(View* view, size_t csr);
+ Rune view_getrune(View* view);
+diff --git a/src/lib/view.c b/src/lib/view.c
+index 40d2865..e6f6a62 100644
+--- a/src/lib/view.c
++++ b/src/lib/view.c
+@@ -204,7 +204,7 @@ void view_byline(View* view, int move, bool extsel) {
+     move_selection(view, extsel, move, buf_byline);
+ }
+-static size_t getoffset(View* view, size_t row, size_t col) {
++size_t view_getoffset(View* view, size_t row, size_t col) {
+     size_t i = 0, y = 0, idx = view->index + row;
+     if (idx >= view->nrows) return 0;
+     Row* selrow = view->rows[idx];
+@@ -215,16 +215,15 @@ static size_t getoffset(View* view, size_t row, size_t col) {
+     return selrow->cols[i].off;
+ }
+-void view_setcursor(View* view, size_t row, size_t col, bool extsel) {
+-    getsel(view)->end = getoffset(view, row, col);
++void view_setcursor(View* view, size_t off, bool extsel) {
++    getsel(view)->end = off;
+     if (!extsel)
+         getsel(view)->beg = getsel(view)->end;
+     buf_getcol(BUF);
+ }
+-void view_selword(View* view, size_t row, size_t col) {
+-    if (row != SIZE_MAX && col != SIZE_MAX)
+-        view_setcursor(view, row, col, false);
++void view_selword(View* view, size_t off) {
++    view_setcursor(view, off, false);
+     buf_selword(BUF, risbigword);
+ }
+@@ -235,8 +234,8 @@ void view_selprev(View* view) {
+         buf_selclr(BUF, RIGHT);
+ }
+-void view_select(View* view, size_t row, size_t col) {
+-    view_setcursor(view, row, col, false);
++void view_select(View* view, size_t off) {
++    view_setcursor(view, off, false);
+     buf_selctx(BUF, risword);
+ }
+@@ -244,12 +243,8 @@ size_t view_selsize(View* view) {
+     return buf_selsz(BUF);
+ }
+-char* view_fetch(View* view, size_t row, size_t col, bool (*isword)(Rune)) {
+-    char* str = NULL;
+-    size_t off = getoffset(view, row, col);
+-    if (off != SIZE_MAX)
+-        str = buf_fetch(BUF, isword, off);
+-    return str;
++char* view_fetch(View* view, size_t off, bool (*isword)(Rune)) {
++    return buf_fetch(BUF, isword, off);
+ }
+ bool view_findstr(View* view, int dir, char* str) {
+diff --git a/src/pick.c b/src/pick.c
+index 9c525cd..503b49d 100644
+--- a/src/pick.c
++++ b/src/pick.c
+@@ -59,7 +59,7 @@ static int by_score(const void* a, const void* b) {
+     else if (ca->score > cb->score)
+         return -1;
+     else
+-        return 0;
++        return strcmp(ca->string, cb->string);
+ }
+ static void load_choices(XConf* x) {
+diff --git a/src/tide.c b/src/tide.c
+index 7a05bc3..28ad559 100644
+--- a/src/tide.c
++++ b/src/tide.c
+@@ -115,7 +115,7 @@ static uint32_t getkey(XConf* x, XEvent* e) {
+     return special_keys(key);
+ }
+-static void mouse_left(WinRegion id, bool pressed, size_t row, size_t col) {
++static void mouse_left(WinRegion id, bool pressed, size_t off) {
+     static int count = 0;
+     static Time before = 0;
+     if (!pressed) return;
+@@ -128,42 +128,42 @@ static void mouse_left(WinRegion id, bool pressed, size_t row, size_t col) {
+         char* arg = NULL;
+         if (!arg || !*arg) arg = view_getstr(win_view(EDIT));
+         if (!arg || !*arg) arg = view_getstr(win_view(TAGS));
+-        char* str = view_fetch(win_view(id), row, col, riscmd);
++        char* str = view_fetch(win_view(id), off, riscmd);
+         if (str) exec(str, arg);
+         free(str);
+         free(arg);
+         ExecRequest = 0;
+     } else {
+         if (count == 1)
+-            view_setcursor(win_view(id), row, col, win_keymodsset(ModShift));
++            view_setcursor(win_view(id), off, win_keymodsset(ModShift));
+         else if (count == 2)
+-            view_select(win_view(id), row, col);
++            view_select(win_view(id), off);
+         else if (count == 3)
+-            view_selword(win_view(id), row, col);
++            view_selword(win_view(id), off);
+     }
+ }
+-static void mouse_middle(WinRegion id, bool pressed, size_t row, size_t col) {
++static void mouse_middle(WinRegion id, bool pressed, size_t off) {
+     if (pressed) { ExecRequest = 1; return; }
+     if (PRESSED(MouseLeft)) {
+         cut(NULL);
+     } else if (ExecRequest) {
+-        char* str = view_fetch(win_view(id), row, col, riscmd);
++        char* str = view_fetch(win_view(id), off, riscmd);
+         if (str) exec(str, NULL);
+         free(str);
+     }
+ }
+-static void mouse_right(WinRegion id, bool pressed, size_t row, size_t col) {
++static void mouse_right(WinRegion id, bool pressed, size_t off) {
+     if (pressed) return;
+     if (PRESSED(MouseLeft)) {
+         paste(NULL);
+     } else {
+-        FetchCmd[2] = view_fetch(win_view(id), row, col, risfile);
++        FetchCmd[2] = view_fetch(win_view(id), off, risfile);
+         if (job_run(FetchCmd) != 0) {
+             SearchDir *= (win_keymodsset(ModShift) ? -1 : +1);
+             free(SearchTerm);
+-            SearchTerm = view_fetch(win_view(id), row, col, risfile);
++            SearchTerm = view_fetch(win_view(id), off, risfile);
+             view_findstr(win_view(EDIT), SearchDir, SearchTerm);
+             SyncMouse = true;
+         }
+@@ -180,10 +180,12 @@ static void mouse_click(int btn, bool pressed, int x, int y) {
+     size_t row, col;
+     Focused = (y <= Divider ? TAGS : EDIT);
+     get_position(Focused, x, y, &row, &col);
++    size_t off = view_getoffset(win_view(Focused), row, col);
++//    printf("B%d %d %lu\n", btn, pressed, off);
+     switch(btn) {
+-        case MouseLeft:    mouse_left(Focused, pressed, row, col);    break;
+-        case MouseMiddle:  mouse_middle(Focused, pressed, row, col);  break;
+-        case MouseRight:   mouse_right(Focused, pressed, row, col);   break;
++        case MouseLeft:    mouse_left(Focused, pressed, off);    break;
++        case MouseMiddle:  mouse_middle(Focused, pressed, off);  break;
++        case MouseRight:   mouse_right(Focused, pressed, off);   break;
+         case MouseWheelUp: mouse_scroll(Focused, pressed, -ScrollBy); break;
+         case MouseWheelDn: mouse_scroll(Focused, pressed, +ScrollBy); break;
+     }
+@@ -225,18 +227,46 @@ static void xkeypress(XConf* x, XEvent* e) {
+         view_insert(win_view(FOCUSED), key);
+ }
++static void xbtnhandle(XConf* x, XEvent* e) {
++    (void)x;
++    bool press = (e->type == ButtonPress);
++    switch (e->xbutton.button) {
++        case Button1:
++            printf("left\n");
++            break;
++
++        case Button2:
++            if (e->xbutton.state & (1 << (Button1 + 7)))
++                printf("left+middle\n");
++            else
++                printf("middle\n");
++            break;
++
++        case Button3:
++            if (e->xbutton.state & (1 << (Button1 + 7)))
++                printf("left+right\n");
++            else
++                printf("right\n");
++            break;
++    }
++    (void)press;
++}
++
+ static void xbtnpress(XConf* x, XEvent* e) {
+     (void)x;
+     Now = e->xbutton.time;
+     KeyBtnState = (e->xbutton.state | (1 << (e->xbutton.button + 7)));
+-    mouse_click(e->xbutton.button, true, e->xbutton.x,  e->xbutton.y);
++(void)mouse_click;
++//    mouse_click(e->xbutton.button, true, e->xbutton.x,  e->xbutton.y);
++    xbtnhandle(x,e);
+ }
+ static void xbtnrelease(XConf* x, XEvent* e) {
+     (void)x;
+     Now = e->xbutton.time;
+     KeyBtnState = (KeyBtnState & ~(1 << (e->xbutton.button + 7)));
+-    mouse_click(e->xbutton.button, false, e->xbutton.x,  e->xbutton.y);
++//    mouse_click(e->xbutton.button, false, e->xbutton.x,  e->xbutton.y);
++    xbtnhandle(x,e);
+ }
+ static void xbtnmotion(XConf* x, XEvent* e) {
+@@ -246,8 +276,9 @@ static void xbtnmotion(XConf* x, XEvent* e) {
+     KeyBtnState = e->xbutton.state;
+     int xpos = e->xbutton.x, ypos = e->xbutton.y;
+     get_position(Focused, xpos, ypos, &row, &col);
++    size_t off = view_getoffset(win_view(Focused), row, col);
+     if (PRESSED(MouseLeft))
+-        view_setcursor(win_view(Focused), row, col, true);
++        view_setcursor(win_view(Focused), off, true);
+ }
+ static void xclientmsg(XConf* x, XEvent* e) {
+@@ -947,6 +978,16 @@ int main(int argc, char** argv) {
+     if (!gethostname(host, sizeof(host)))
+         win_prop_set("HOST", "host", host);
++    /* check if we should embede in a parent */
++    char* winid = getenv("TIDE_PARENT");
++    if (winid)
++    {
++        Window parent = strtoul(winid, 0, 0);
++        XReparentWindow(X.display, X.self, parent, 0, 0);
++        XFlush(X.display);
++    }
++
++
+     /* now create the window and start the event loop */
+     xupdate(NULL);
+     win_loop();