diff options
| author | Jari Vetoniemi <mailroxas@gmail.com> | 2014-10-25 20:02:34 +0300 | 
|---|---|---|
| committer | Jari Vetoniemi <mailroxas@gmail.com> | 2014-10-25 20:02:34 +0300 | 
| commit | d3db039136ad66d2c83c1c0fbf0964bfbb5afb16 (patch) | |
| tree | 93af6d73ad168e0169183a9c4f625acd5492e08c /lib/renderers | |
| parent | 2820734ec01ad6d2e1a0611fa480c3dd533588c7 (diff) | |
| download | bemenu-d3db039136ad66d2c83c1c0fbf0964bfbb5afb16.tar.gz bemenu-d3db039136ad66d2c83c1c0fbf0964bfbb5afb16.tar.bz2 bemenu-d3db039136ad66d2c83c1c0fbf0964bfbb5afb16.zip  | |
Single line mode, color customization, etc..
Diffstat (limited to 'lib/renderers')
| -rw-r--r-- | lib/renderers/cairo.h | 172 | ||||
| -rw-r--r-- | lib/renderers/curses/curses.c | 14 | ||||
| -rw-r--r-- | lib/renderers/wayland/wayland.c | 44 | ||||
| -rw-r--r-- | lib/renderers/wayland/wayland.h | 3 | ||||
| -rw-r--r-- | lib/renderers/wayland/window.c | 92 | 
5 files changed, 225 insertions, 100 deletions
diff --git a/lib/renderers/cairo.h b/lib/renderers/cairo.h index 9c1ff5a..1dc052f 100644 --- a/lib/renderers/cairo.h +++ b/lib/renderers/cairo.h @@ -6,6 +6,10 @@  #include <assert.h>  #include <cairo/cairo.h> +#ifndef MAX +#  define MAX(a,b) (((a)>(b))?(a):(b)) +#endif +  struct cairo {      cairo_t *cr;      cairo_surface_t *surface; @@ -15,26 +19,23 @@ struct cairo_color {      float r, g, b, a;  }; -struct cairo_font { -    const char *name; -    uint32_t size; -}; -  struct cairo_paint { -    struct cairo_color color; -    struct cairo_font font; +    struct cairo_color fg; +    struct cairo_color bg; +    cairo_font_extents_t fe;  };  struct cairo_result {      cairo_text_extents_t te;  }; -__attribute__((unused)) BM_LOG_ATTR(6, 7) static bool -bm_cairo_draw_line(struct cairo *cairo, struct cairo_paint *paint, struct cairo_result *result, int32_t x, int32_t y, const char *fmt, ...) +static size_t blen = 0; +static char *buffer = NULL; + +__attribute__((unused)) BM_LOG_ATTR(3, 4) static bool +bm_cairo_get_text_extents(struct cairo *cairo, struct cairo_result *result, const char *fmt, ...)  { -    static size_t blen = 0; -    static char *buffer = NULL; -    assert(cairo && paint && result && fmt); +    assert(cairo && result && fmt);      memset(result, 0, sizeof(struct cairo_result));      va_list args; @@ -45,13 +46,33 @@ bm_cairo_draw_line(struct cairo *cairo, struct cairo_paint *paint, struct cairo_      if (!ret)          return false; -    cairo_set_source_rgba(cairo->cr, paint->color.r, paint->color.b, paint->color.g, paint->color.a); +    cairo_text_extents(cairo->cr, buffer, &result->te); +    return true; +} + +__attribute__((unused)) BM_LOG_ATTR(8, 9) static bool +bm_cairo_draw_line(struct cairo *cairo, struct cairo_paint *paint, struct cairo_result *result, uint32_t xoff, uint32_t w, int32_t x, int32_t y, const char *fmt, ...) +{ +    assert(cairo && paint && result && fmt); +    memset(result, 0, sizeof(struct cairo_result)); + +    va_list args; +    va_start(args, fmt); +    bool ret = bm_vrprintf(&buffer, &blen, fmt, args); +    va_end(args); + +    if (!ret) +        return false;      cairo_text_extents_t te; -    cairo_select_font_face(cairo->cr, paint->font.name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); -    cairo_set_font_size(cairo->cr, paint->font.size);      cairo_text_extents(cairo->cr, buffer, &te); -    cairo_move_to(cairo->cr, x, y * te.height + te.height); + +    cairo_set_source_rgba(cairo->cr, paint->bg.r, paint->bg.b, paint->bg.g, paint->bg.a); +    cairo_rectangle(cairo->cr, x - xoff, y, (w > 0 ? w : te.width) + xoff, paint->fe.height); +    cairo_fill(cairo->cr); + +    cairo_set_source_rgba(cairo->cr, paint->fg.r, paint->fg.b, paint->fg.g, paint->fg.a); +    cairo_move_to(cairo->cr, x, y + paint->fe.descent + paint->fe.height * 0.5);      cairo_show_text(cairo->cr, buffer);      memcpy(&result->te, &te, sizeof(te)); @@ -59,41 +80,108 @@ bm_cairo_draw_line(struct cairo *cairo, struct cairo_paint *paint, struct cairo_  }  __attribute__((unused)) static void +bm_cairo_color_from_menu_color(const struct bm_menu *menu, enum bm_color color, struct cairo_color *c) +{ +    assert(menu); +    c->r = (float)menu->colors[color].r / 255.0f; +    c->g = (float)menu->colors[color].g / 255.0f; +    c->b = (float)menu->colors[color].b / 255.0f; +    c->a = 1.0f; +} + +__attribute__((unused)) static uint32_t  bm_cairo_paint(struct cairo *cairo, uint32_t width, uint32_t height, const struct bm_menu *menu)  { -    cairo_set_source_rgb(cairo->cr, 18.0f / 255.0f, 18 / 255.0f, 18.0f / 255.0f); +    assert(cairo && menu); + +    struct cairo_color c; +    bm_cairo_color_from_menu_color(menu, BM_COLOR_BG, &c); +    cairo_set_source_rgb(cairo->cr, c.r, c.g, c.b);      cairo_rectangle(cairo->cr, 0, 0, width, height);      cairo_fill(cairo->cr); -    struct cairo_result result; -    memset(&result, 0, sizeof(result)); +    cairo_select_font_face(cairo->cr, menu->font.name, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); +    cairo_set_font_size(cairo->cr, menu->font.size);      struct cairo_paint paint;      memset(&paint, 0, sizeof(paint)); -    paint.font.name = "Terminus"; -    paint.font.size = 12; -    paint.color = (struct cairo_color){ 1.0, 0.0, 0.0, 1.0 }; - -    if (menu->title) -        bm_cairo_draw_line(cairo, &paint, &result, result.te.x_advance, 0, "%s ", menu->title); -    if (menu->filter) -        bm_cairo_draw_line(cairo, &paint, &result, result.te.x_advance, 0, "%s", menu->filter); - -    uint32_t count, cl = 1; -    uint32_t lines = height / paint.font.size; -    struct bm_item **items = bm_menu_get_filtered_items(menu, &count); -    for (uint32_t i = (menu->index / (lines - 1)) * (lines - 1); i < count && cl < lines; ++i) { -        bool highlighted = (items[i] == bm_menu_get_highlighted_item(menu)); - -        if (highlighted) -            paint.color = (struct cairo_color){ 1.0, 0.0, 0.0, 1.0 }; -        else if (bm_menu_item_is_selected(menu, items[i])) -            paint.color = (struct cairo_color){ 1.0, 0.0, 0.0, 1.0 }; -        else -            paint.color = (struct cairo_color){ 1.0, 1.0, 1.0, 1.0 }; - -        bm_cairo_draw_line(cairo, &paint, &result, 0, cl++, "%s%s", (highlighted ? ">> " : "   "), (items[i]->text ? items[i]->text : "")); +    cairo_font_extents(cairo->cr, &paint.fe); + +    struct cairo_result result; +    memset(&result, 0, sizeof(result)); + +    if (menu->title) { +        bm_cairo_color_from_menu_color(menu, BM_COLOR_TITLE_FG, &paint.fg); +        bm_cairo_color_from_menu_color(menu, BM_COLOR_TITLE_BG, &paint.bg); +        bm_cairo_draw_line(cairo, &paint, &result, 0, 0, result.te.x_advance, 4, "%s", menu->title); +    } + +    bm_cairo_color_from_menu_color(menu, BM_COLOR_FILTER_FG, &paint.fg); +    bm_cairo_color_from_menu_color(menu, BM_COLOR_FILTER_BG, &paint.bg); +    bm_cairo_draw_line(cairo, &paint, &result, 0, width, result.te.x_advance, 4, "%s%s", (menu->title ? " " : ""), (menu->filter ? menu->filter : "")); + +    uint32_t displayed = 1; +    uint32_t lines = MAX(height / paint.fe.height, menu->lines); +    if (lines > 1) { +        uint32_t count, cl = 1; +        struct bm_item **items = bm_menu_get_filtered_items(menu, &count); +        for (uint32_t i = (menu->index / (lines - 1)) * (lines - 1); i < count && cl < lines; ++i) { +            bool highlighted = (items[i] == bm_menu_get_highlighted_item(menu)); + +            if (highlighted) { +                bm_cairo_color_from_menu_color(menu, BM_COLOR_HIGHLIGHTED_FG, &paint.fg); +                bm_cairo_color_from_menu_color(menu, BM_COLOR_HIGHLIGHTED_BG, &paint.bg); +            } else if (bm_menu_item_is_selected(menu, items[i])) { +                bm_cairo_color_from_menu_color(menu, BM_COLOR_SELECTED_FG, &paint.fg); +                bm_cairo_color_from_menu_color(menu, BM_COLOR_SELECTED_BG, &paint.bg); +            } else { +                bm_cairo_color_from_menu_color(menu, BM_COLOR_ITEM_FG, &paint.fg); +                bm_cairo_color_from_menu_color(menu, BM_COLOR_ITEM_BG, &paint.bg); +            } + +            bm_cairo_draw_line(cairo, &paint, &result, 0, width, 0, 4 + paint.fe.height * cl++, +                    "%s%s", (highlighted ? ">> " : "   "), (items[i]->text ? items[i]->text : "")); + +            ++displayed; +        } +    } else { +        uint32_t count; +        struct bm_item **items = bm_menu_get_filtered_items(menu, &count); + +        uint32_t cl = width / 4; +        if (menu->wrap || menu->index > 0) { +            bm_cairo_draw_line(cairo, &paint, &result, 0, 0, cl, 4, "<"); +            cl += result.te.x_advance + 4; +        } + +        for (uint32_t i = menu->index; i < count && cl < width; ++i) { +            bool highlighted = (items[i] == bm_menu_get_highlighted_item(menu)); + +            if (highlighted) { +                bm_cairo_color_from_menu_color(menu, BM_COLOR_HIGHLIGHTED_FG, &paint.fg); +                bm_cairo_color_from_menu_color(menu, BM_COLOR_HIGHLIGHTED_BG, &paint.bg); +            } else if (bm_menu_item_is_selected(menu, items[i])) { +                bm_cairo_color_from_menu_color(menu, BM_COLOR_SELECTED_FG, &paint.fg); +                bm_cairo_color_from_menu_color(menu, BM_COLOR_SELECTED_BG, &paint.bg); +            } else { +                bm_cairo_color_from_menu_color(menu, BM_COLOR_ITEM_FG, &paint.fg); +                bm_cairo_color_from_menu_color(menu, BM_COLOR_ITEM_BG, &paint.bg); +            } + +            bm_cairo_draw_line(cairo, &paint, &result, 0, 0, cl, 4, "%s", (items[i]->text ? items[i]->text : "")); +            cl += result.te.x_advance + 4; +            displayed += (cl < width); +        } + +        if (menu->wrap || menu->index + 1 < count) { +            bm_cairo_color_from_menu_color(menu, BM_COLOR_FILTER_FG, &paint.fg); +            bm_cairo_color_from_menu_color(menu, BM_COLOR_FILTER_BG, &paint.bg); +            bm_cairo_get_text_extents(cairo, &result, ">"); +            bm_cairo_draw_line(cairo, &paint, &result, 4, result.te.x_advance + 4, width - result.te.x_advance - 4, 4, ">"); +        }      } + +    return displayed;  }  #endif /* _BM_CAIRO_H */ diff --git a/lib/renderers/curses/curses.c b/lib/renderers/curses/curses.c index c40e833..5771afa 100644 --- a/lib/renderers/curses/curses.c +++ b/lib/renderers/curses/curses.c @@ -156,7 +156,6 @@ render(const struct bm_menu *menu)          init_pair(2, COLOR_RED, -1);      } -    const uint32_t lines = getmaxy(curses.stdscr);      erase();      uint32_t ncols = getmaxx(curses.stdscr); @@ -183,11 +182,14 @@ render(const struct bm_menu *menu)      }      uint32_t count, cl = 1; -    struct bm_item **items = bm_menu_get_filtered_items(menu, &count); -    for (uint32_t i = (menu->index / (lines - 1)) * (lines - 1); i < count && cl < lines; ++i) { -        bool highlighted = (items[i] == bm_menu_get_highlighted_item(menu)); -        int32_t color = (highlighted ? 2 : (bm_menu_item_is_selected(menu, items[i]) ? 1 : 0)); -        draw_line(color, cl++, "%s%s", (highlighted ? ">> " : "   "), (items[i]->text ? items[i]->text : "")); +    const uint32_t lines = getmaxy(curses.stdscr); +    if (lines > 1) { +        struct bm_item **items = bm_menu_get_filtered_items(menu, &count); +        for (uint32_t i = (menu->index / (lines - 1)) * (lines - 1); i < count && cl < lines; ++i) { +            bool highlighted = (items[i] == bm_menu_get_highlighted_item(menu)); +            int32_t color = (highlighted ? 2 : (bm_menu_item_is_selected(menu, items[i]) ? 1 : 0)); +            draw_line(color, cl++, "%s%s", (highlighted ? ">> " : "   "), (items[i]->text ? items[i]->text : "")); +        }      }      move(0, title_len + (menu->curses_cursor < ccols ? menu->curses_cursor : ccols)); diff --git a/lib/renderers/wayland/wayland.c b/lib/renderers/wayland/wayland.c index 0d5fcde..c6f8f8b 100644 --- a/lib/renderers/wayland/wayland.c +++ b/lib/renderers/wayland/wayland.c @@ -11,6 +11,9 @@ static void  render(const struct bm_menu *menu)  {      struct wayland *wayland = menu->renderer->internal; +    uint32_t count; +    bm_menu_get_filtered_items(menu, &count); +    wayland->window.height = ((count < menu->lines ? count : menu->lines) + 1) * menu->font.size + 4;      bm_wl_window_render(&wayland->window, menu);      wl_display_dispatch(wayland->display);  } @@ -25,6 +28,7 @@ poll_key(const struct bm_menu *menu, unsigned int *unicode)      if (wayland->input.sym == XKB_KEY_NoSymbol)          return BM_KEY_UNICODE; +    uint32_t mods = wayland->input.modifiers;      *unicode = xkb_state_key_get_utf32(wayland->input.xkb.state, wayland->input.code);      switch (wayland->input.sym) { @@ -47,16 +51,16 @@ poll_key(const struct bm_menu *menu, unsigned int *unicode)              return BM_KEY_END;          case XKB_KEY_SunPageUp: -            return BM_KEY_PAGE_UP; +            return (mods & MOD_SHIFT ? BM_KEY_SHIFT_PAGE_UP : BM_KEY_PAGE_UP);          case XKB_KEY_SunPageDown: -            return BM_KEY_PAGE_DOWN; +            return (mods & MOD_SHIFT ? BM_KEY_SHIFT_PAGE_DOWN : BM_KEY_PAGE_DOWN);          case XKB_KEY_BackSpace:              return BM_KEY_BACKSPACE;          case XKB_KEY_Delete: -            return BM_KEY_DELETE; +            return (mods & MOD_SHIFT ? BM_KEY_LINE_DELETE_LEFT : BM_KEY_DELETE);          case XKB_KEY_Tab:              return BM_KEY_TAB; @@ -65,11 +69,41 @@ poll_key(const struct bm_menu *menu, unsigned int *unicode)              return BM_KEY_SHIFT_RETURN;          case XKB_KEY_Return: -            return BM_KEY_RETURN; +            return (mods & MOD_CTRL ? BM_KEY_CONTROL_RETURN : (mods & MOD_SHIFT ? BM_KEY_SHIFT_RETURN : BM_KEY_RETURN));          case XKB_KEY_Escape:              return BM_KEY_ESCAPE; +        case XKB_KEY_p: +            return (mods & MOD_CTRL ? BM_KEY_UP : BM_KEY_UNICODE); + +        case XKB_KEY_n: +            return (mods & MOD_CTRL ? BM_KEY_DOWN : BM_KEY_UNICODE); + +        case XKB_KEY_l: +            return (mods & MOD_CTRL ? BM_KEY_LEFT : BM_KEY_UNICODE); + +        case XKB_KEY_f: +            return (mods & MOD_CTRL ? BM_KEY_RIGHT : BM_KEY_UNICODE); + +        case XKB_KEY_a: +            return (mods & MOD_CTRL ? BM_KEY_HOME : BM_KEY_UNICODE); + +        case XKB_KEY_e: +            return (mods & MOD_CTRL ? BM_KEY_END : BM_KEY_UNICODE); + +        case XKB_KEY_h: +            return (mods & MOD_CTRL ? BM_KEY_BACKSPACE : BM_KEY_UNICODE); + +        case XKB_KEY_u: +            return (mods & MOD_CTRL ? BM_KEY_LINE_DELETE_LEFT : BM_KEY_UNICODE); + +        case XKB_KEY_k: +            return (mods & MOD_CTRL ? BM_KEY_LINE_DELETE_RIGHT : BM_KEY_UNICODE); + +        case XKB_KEY_w: +            return (mods & MOD_CTRL ? BM_KEY_WORD_DELETE : BM_KEY_UNICODE); +          default: break;      } @@ -81,7 +115,7 @@ get_displayed_count(const struct bm_menu *menu)  {      struct wayland *wayland = menu->renderer->internal;      assert(wayland); -    return wayland->window.height / 12; +    return wayland->window.displayed;  }  static void diff --git a/lib/renderers/wayland/wayland.h b/lib/renderers/wayland/wayland.h index fd29405..d698218 100644 --- a/lib/renderers/wayland/wayland.h +++ b/lib/renderers/wayland/wayland.h @@ -70,9 +70,10 @@ struct window {      struct wl_shm *shm;      struct buffer buffers[2];      uint32_t width, height; +    uint32_t displayed;      struct { -        void (*render)(struct cairo *cairo, uint32_t width, uint32_t height, const struct bm_menu *menu); +        uint32_t (*render)(struct cairo *cairo, uint32_t width, uint32_t height, const struct bm_menu *menu);      } notify;  }; diff --git a/lib/renderers/wayland/window.c b/lib/renderers/wayland/window.c index 9234ef2..21555b8 100644 --- a/lib/renderers/wayland/window.c +++ b/lib/renderers/wayland/window.c @@ -13,79 +13,79 @@  static int  set_cloexec_or_close(int fd)  { -   if (fd == -1) -      return -1; +    if (fd == -1) +        return -1; -   long flags = fcntl(fd, F_GETFD); -   if (flags == -1) -      goto err; +    long flags = fcntl(fd, F_GETFD); +    if (flags == -1) +        goto err; -   if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) -      goto err; +    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) +        goto err; -   return fd; +    return fd;  err: -   close(fd); -   return -1; +    close(fd); +    return -1;  }  static int  create_tmpfile_cloexec(char *tmpname)  { -   int fd; +    int fd;  #ifdef HAVE_MKOSTEMP -   if ((fd = mkostemp(tmpname, O_CLOEXEC)) >= 0) -      unlink(tmpname); +    if ((fd = mkostemp(tmpname, O_CLOEXEC)) >= 0) +        unlink(tmpname);  #else -   if ((fd = mkstemp(tmpname)) >= 0) { -      fd = set_cloexec_or_close(fd); -      unlink(tmpname); -   } +    if ((fd = mkstemp(tmpname)) >= 0) { +        fd = set_cloexec_or_close(fd); +        unlink(tmpname); +    }  #endif -   return fd; +    return fd;  }  static int  os_create_anonymous_file(off_t size)  { -   static const char template[] = "/bemenu-shared-XXXXXX"; -   int fd; -   int ret; - -   const char *path; -   if (!(path = getenv("XDG_RUNTIME_DIR")) || strlen(path) <= 0) { -      errno = ENOENT; -      return -1; -   } +    static const char template[] = "/bemenu-shared-XXXXXX"; +    int fd; +    int ret; + +    const char *path; +    if (!(path = getenv("XDG_RUNTIME_DIR")) || strlen(path) <= 0) { +        errno = ENOENT; +        return -1; +    } -   char *name; -   int ts = (path[strlen(path) - 1] == '/'); -   if (!(name = bm_dprintf("%s%s%s", path, (ts ? "" : "/"), template))) -      return -1; +    char *name; +    int ts = (path[strlen(path) - 1] == '/'); +    if (!(name = bm_dprintf("%s%s%s", path, (ts ? "" : "/"), template))) +        return -1; -   fd = create_tmpfile_cloexec(name); -   free(name); +    fd = create_tmpfile_cloexec(name); +    free(name); -   if (fd < 0) -      return -1; +    if (fd < 0) +        return -1;  #ifdef HAVE_POSIX_FALLOCATE -   if ((ret = posix_fallocate(fd, 0, size)) != 0) { -      close(fd); -      errno = ret; -      return -1; -   } +    if ((ret = posix_fallocate(fd, 0, size)) != 0) { +        close(fd); +        errno = ret; +        return -1; +    }  #else -   if ((ret = ftruncate(fd, size)) < 0) { -      close(fd); -      return -1; -   } +    if ((ret = ftruncate(fd, size)) < 0) { +        close(fd); +        return -1; +    }  #endif -   return fd; +    return fd;  }  static void @@ -256,7 +256,7 @@ bm_wl_window_render(struct window *window, const struct bm_menu *menu)          return;      if (window->notify.render) -        window->notify.render(&buffer->cairo, buffer->width, buffer->height, menu); +        window->displayed = window->notify.render(&buffer->cairo, buffer->width, buffer->height, menu);      wl_surface_damage(window->surface, 0, 0, buffer->width, buffer->height);      wl_surface_attach(window->surface, buffer->buffer, 0, 0);  | 
