From: Michael D. Lowis Date: Fri, 31 May 2019 15:24:36 +0000 (-0400) Subject: added borders and color to windows and titlebar X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=2f795426afc7edc68e9465429765522d382424d5;p=projs%2Ftide.git added borders and color to windows and titlebar --- diff --git a/hulksmash.c b/hulksmash.c new file mode 100644 index 0000000..777cc1d --- /dev/null +++ b/hulksmash.c @@ -0,0 +1,309 @@ +/* (The MIT License) + * + * Copyright (c) 2014 Arran Cudbard-Bell + * + * 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 +#include +#include + +#include +#include + +#include + +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 Polling interval\n"); + fprintf(output, " -o Command to execute when button lid is open.\n"); + fprintf(output, " -c Command to execute when button lid is closed.\n"); + fprintf(output, " -p Command to execute when button is pressed.\n"); + fprintf(output, " -r 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); +} diff --git a/src/anvil.c b/src/anvil.c index 0ee12a9..a8af2eb 100644 --- a/src/anvil.c +++ b/src/anvil.c @@ -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 index 0000000..a1c196e --- /dev/null +++ b/testsed.sh @@ -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 index 0000000..48aca40 --- /dev/null +++ b/view_rework.diff @@ -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();