diff options
author | Phil Jones <philj56@gmail.com> | 2021-11-15 19:37:48 +0000 |
---|---|---|
committer | Phil Jones <philj56@gmail.com> | 2021-11-15 19:37:48 +0000 |
commit | 49c7405b6a88e56bb69e12189adb719927343e07 (patch) | |
tree | 72c7691e746563cc1396c5b555659c813572c12e | |
parent | 108df42e561b7e81ba09a8c278a562129e651bb6 (diff) |
Multiple smaller changes.
- Remove the background image and libpng dependency
- Add a prompt
- Add xmalloc with out-of-memory handling
- Add beginnings of a rofi-like run cache
-rw-r--r-- | meson.build | 5 | ||||
-rw-r--r-- | src/compgen.c | 57 | ||||
-rw-r--r-- | src/entry.c | 19 | ||||
-rw-r--r-- | src/entry.h | 1 | ||||
-rw-r--r-- | src/gl.c | 5 | ||||
-rw-r--r-- | src/image.c | 96 | ||||
-rw-r--r-- | src/image.h | 2 | ||||
-rw-r--r-- | src/ipc.c | 3 | ||||
-rw-r--r-- | src/main.c | 32 | ||||
-rw-r--r-- | src/string_vec.c | 7 | ||||
-rw-r--r-- | src/string_vec.h | 5 | ||||
-rw-r--r-- | src/tofi.h | 5 | ||||
-rw-r--r-- | src/xmalloc.c | 42 | ||||
-rw-r--r-- | src/xmalloc.h | 14 |
14 files changed, 158 insertions, 135 deletions
diff --git a/meson.build b/meson.build index 344cfcd..ea1db95 100644 --- a/meson.build +++ b/meson.build @@ -67,12 +67,12 @@ sources = files( 'src/egl.c', 'src/entry.c', 'src/gl.c', - 'src/image.c', 'src/ipc.c', 'src/log.c', 'src/string_vec.c', 'src/surface.c', 'src/wlr-layer-shell-unstable-v1.c', + 'src/xmalloc.c', ) cc = meson.get_compiler('c') @@ -80,7 +80,6 @@ epoxy = dependency('epoxy') glib = dependency('glib-2.0') json = dependency('json-c') pangocairo = dependency('pangocairo') -png = dependency('libpng') wayland_client = dependency('wayland-client') wayland_egl = dependency('wayland-egl') wayland_protocols = dependency('wayland-protocols', native: true) @@ -119,7 +118,7 @@ endforeach executable( 'tofi', sources, wl_proto_src, wl_proto_headers, - dependencies: [epoxy, json, glib, pangocairo, png, wayland_egl, xkbcommon], + dependencies: [epoxy, json, glib, pangocairo, wayland_egl, xkbcommon], install: true ) diff --git a/src/compgen.c b/src/compgen.c index e04e0a5..8190a21 100644 --- a/src/compgen.c +++ b/src/compgen.c @@ -1,16 +1,71 @@ #include <dirent.h> +#include <stdbool.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include "log.h" #include "string_vec.h" +#include "xmalloc.h" + +static const char *default_state_dir = ".local/state"; +static const char *histfile_basename = "tofi-history"; + +static char *get_histfile_path() { + char *histfile_name; + const char *state_path = getenv("XDG_STATE_HOME"); + if (state_path == NULL) { + const char *home = getenv("HOME"); + if (home == NULL) { + log_error("Couldn't retrieve HOME from environment.\n"); + exit(EXIT_FAILURE); + } + size_t len = strlen(home) + 1 + + strlen(default_state_dir) + 1 + + strlen(histfile_basename) + 1; + histfile_name = xmalloc(len); + snprintf( + histfile_name, + len, + "%s/%s/%s", + home, + default_state_dir, + histfile_basename); + } else { + size_t len = strlen(state_path) + 1 + + strlen(histfile_basename) + 1; + histfile_name = xmalloc(len); + snprintf( + histfile_name, + len, + "%s/%s", + state_path, + histfile_basename); + } + return histfile_name; + +} + +static void load_history() +{ + char *name = get_histfile_path(); + FILE *histfile = fopen(name, "rb"); + + free(name); + + if (histfile == NULL) { + return; + } + +} struct string_vec compgen() { + load_history(); log_debug("Retrieving PATH.\n"); const char *env_path = getenv("PATH"); if (env_path == NULL) { - log_error("Couldn't retrieve PATH from environment."); + log_error("Couldn't retrieve PATH from environment.\n"); exit(EXIT_FAILURE); } struct string_vec programs = string_vec_create(); diff --git a/src/entry.c b/src/entry.c index def32b2..644fe39 100644 --- a/src/entry.c +++ b/src/entry.c @@ -100,6 +100,24 @@ void entry_init(struct entry *entry, uint32_t width, uint32_t height, uint32_t s pango_context_set_font_description(context, font_description); pango_font_description_free(font_description); + entry->pango.prompt_layout = pango_layout_new(context); + pango_layout_set_text(entry->pango.prompt_layout, "run: ", -1); + int prompt_width; + int prompt_height; + pango_layout_get_pixel_size(entry->pango.prompt_layout, &prompt_width, &prompt_height); + pango_cairo_update_layout(cr, entry->pango.prompt_layout); + + /* Draw the prompt now, as this only needs to be done once */ + color = entry->foreground_color; + cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a); + pango_cairo_show_layout(cr, entry->pango.prompt_layout); + + /* Move and clip so we don't draw over the prompt */ + cairo_translate(cr, prompt_width, 0); + width -= prompt_width; + cairo_rectangle(cr, 0, 0, width, height); + cairo_clip(cr); + entry->pango.entry_layout = pango_layout_new(context); pango_layout_set_text(entry->pango.entry_layout, "", -1); @@ -123,6 +141,7 @@ void entry_destroy(struct entry *entry) g_object_unref(entry->pango.result_layouts[i]); } g_object_unref(entry->pango.entry_layout); + g_object_unref(entry->pango.prompt_layout); g_object_unref(entry->pango.context); cairo_destroy(entry->cairo.cr); cairo_surface_destroy(entry->cairo.surface); diff --git a/src/entry.h b/src/entry.h index a362ec9..6d4023f 100644 --- a/src/entry.h +++ b/src/entry.h @@ -13,6 +13,7 @@ struct entry { struct image image; struct { PangoContext *context; + PangoLayout *prompt_layout; PangoLayout *entry_layout; PangoLayout *result_layouts[5]; } pango; @@ -5,6 +5,7 @@ #include <string.h> #include "gl.h" #include "log.h" +#include "xmalloc.h" #define max(a, b) ((a) > (b) ? (a) : (b)) @@ -197,7 +198,7 @@ void load_shader(GLuint shader, const char *filename) exit(EXIT_FAILURE); } unsigned long usize = (unsigned long) size; - GLchar *source = malloc(usize + 1); + GLchar *source = xmalloc(usize + 1); rewind(fp); if (fread(source, 1, usize, fp) != usize) { log_error("Failed to load shader %s: %s.\n", @@ -220,7 +221,7 @@ void load_shader(GLuint shader, const char *filename) GLint info_length = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_length); if (info_length > 1) { - char *log = malloc((unsigned)info_length * sizeof(*log)); + char *log = xmalloc((unsigned)info_length * sizeof(*log)); glGetShaderInfoLog(shader, info_length, NULL, log); log_error("\t%s\n", log); free(log); diff --git a/src/image.c b/src/image.c deleted file mode 100644 index 07195c1..0000000 --- a/src/image.c +++ /dev/null @@ -1,96 +0,0 @@ -#include <errno.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <png.h> -#include "log.h" -#include "image.h" - -#define HEADER_BYTES 8 - -void image_load(struct image *image, const char *filename) -{ - log_debug("Loading image '%s'\n", filename); - FILE *fp = fopen(filename, "rb"); - uint8_t header[HEADER_BYTES]; - if (!fp) { - log_error("Couldn't open '%s': %s.\n", - filename, strerror(errno)); - return; - } - if (fread(header, 1, HEADER_BYTES, fp) != HEADER_BYTES) { - log_error("Failed to read '%s': %s.\n", - filename, strerror(errno)); - fclose(fp); - return; - } - if (png_sig_cmp(header, 0, HEADER_BYTES)) { - log_error("'%s' isn't a PNG file.\n", filename); - fclose(fp); - return; - } - - png_structp png_ptr = png_create_read_struct( - PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL); - if (!png_ptr) { - log_error("Couldn't create PNG read struct.\n"); - fclose(fp); - return; - } - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, NULL, NULL); - fclose(fp); - log_error("Couldn't create PNG info struct.\n"); - return; - } - - if (setjmp(png_jmpbuf(png_ptr)) != 0) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(fp); - log_error("Couldn't setjmp for libpng.\n"); - return; - } - - png_init_io(png_ptr, fp); - png_set_sig_bytes(png_ptr, HEADER_BYTES); - png_read_info(png_ptr, info_ptr); - - uint32_t width = png_get_image_width(png_ptr, info_ptr); - uint32_t height = png_get_image_height(png_ptr, info_ptr); - //uint8_t color_type = png_get_color_type(png_ptr, info_ptr); - //uint8_t bit_depth = png_get_bit_depth(png_ptr, info_ptr); - - png_set_expand(png_ptr); - png_set_gray_to_rgb(png_ptr); - png_set_filler(png_ptr, 0xFFu, PNG_FILLER_AFTER); - - png_read_update_info(png_ptr, info_ptr); - - uint32_t row_bytes = png_get_rowbytes(png_ptr, info_ptr); - /* Guard against integer overflow */ - if (height > PNG_SIZE_MAX / row_bytes) { - png_error(png_ptr, "image_data buffer would be too large"); - } - - png_bytep buffer = malloc(height * row_bytes); - png_bytepp row_pointers = calloc(height, sizeof(png_bytep)); - for (uint32_t y = 0; y < height; y++) { - row_pointers[y] = &buffer[y * row_bytes]; - } - - png_read_image(png_ptr, row_pointers); - png_read_end(png_ptr, NULL); - - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - free(row_pointers); - fclose(fp); - - image->width = width; - image->height = height; - image->buffer = buffer; - log_debug("Image loaded.\n"); -} diff --git a/src/image.h b/src/image.h index 21b9100..a66e0cb 100644 --- a/src/image.h +++ b/src/image.h @@ -18,6 +18,4 @@ struct image { } damage; }; -void image_load(struct image *image, const char *filename); - #endif /* IMAGE_H */ @@ -9,6 +9,7 @@ #include <unistd.h> #include "ipc.h" #include "log.h" +#include "xmalloc.h" static int ipc_open(void); static int ipc_send(int socket, struct json_object *request); @@ -99,7 +100,7 @@ struct json_object *ipc_receive(int sock) return NULL; } - char *buf = malloc(len + 1); + char *buf = xmalloc(len + 1); if (recv(sock, buf, len, 0) != len) { log_error("Error receiving response: %s\n", strerror(errno)); free(buf); @@ -53,16 +53,6 @@ static void resize(struct tofi *tofi) * Wayland wants "surface-local" width / height, so we have to divide * the entry's pixel size by the scale factor. */ - //int32_t x = ( - // tofi->window.width - // - entry_surface->width / tofi->window.scale - // ) / 2; - //int32_t y = ( - // tofi->window.height - // - entry_surface->height / tofi->window.scale - // ) / 2; - //wl_subsurface_set_position(tofi->window.entry.wl_subsurface, x, y); - //wl_surface_commit(tofi->window.entry.surface.wl_surface); } static void zwlr_layer_surface_configure( @@ -603,7 +593,6 @@ int main(int argc, char *argv[]) /* Option parsing with getopt. */ struct option long_options[] = { - {"background-image", required_argument, NULL, 'b'}, {"background-color", required_argument, NULL, 'B'}, {"border-width", required_argument, NULL, 'r'}, {"border-color", required_argument, NULL, 'R'}, @@ -626,11 +615,6 @@ int main(int argc, char *argv[]) int opt = getopt_long(argc, argv, short_options, long_options, NULL); while (opt != -1) { switch (opt) { - case 'b': - image_load( - &tofi.window.background_image, - optarg); - break; case 'B': tofi.window.background_color = hex_to_color(optarg); @@ -772,11 +756,11 @@ int main(int argc, char *argv[]) tofi.zwlr_layer_shell, tofi.window.surface.wl_surface, tofi.wl_output, - ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, + ZWLR_LAYER_SHELL_V1_LAYER_TOP, "launcher"); zwlr_layer_surface_v1_set_keyboard_interactivity( tofi.window.zwlr_layer_surface, - ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE + ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND ); zwlr_layer_surface_v1_add_listener( tofi.window.zwlr_layer_surface, @@ -791,6 +775,10 @@ int main(int argc, char *argv[]) zwlr_layer_surface_v1_set_exclusive_zone( tofi.window.zwlr_layer_surface, -1); + zwlr_layer_surface_v1_set_size( + tofi.window.zwlr_layer_surface, + 800, + 400); wl_surface_commit(tofi.window.surface.wl_surface); /* @@ -834,7 +822,7 @@ int main(int argc, char *argv[]) &tofi.window.entry.image); surface_draw( &tofi.window.surface, - &tofi.window.background_color, + &tofi.window.entry.background_color, &tofi.window.entry.image); /* @@ -855,7 +843,7 @@ int main(int argc, char *argv[]) if (tofi.window.surface.redraw) { surface_draw( &tofi.window.surface, - &tofi.window.background_color, + &tofi.window.entry.background_color, &tofi.window.entry.image); tofi.window.surface.redraw = false; } @@ -876,10 +864,6 @@ int main(int argc, char *argv[]) */ entry_destroy(&tofi.window.entry); surface_destroy(&tofi.window.surface); - if (tofi.window.background_image.buffer != NULL) { - free(tofi.window.background_image.buffer); - tofi.window.background_image.buffer = NULL; - } eglTerminate(tofi.window.surface.egl.display); wl_surface_destroy(tofi.window.surface.wl_surface); if (tofi.wl_keyboard != NULL) { diff --git a/src/string_vec.c b/src/string_vec.c index f747339..d3ac9fe 100644 --- a/src/string_vec.c +++ b/src/string_vec.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include <string.h> #include "string_vec.h" +#include "xmalloc.h" static int cmpstringp(const void *restrict a, const void *restrict b) { @@ -29,7 +30,7 @@ struct string_vec string_vec_create(void) struct string_vec vec = { .count = 0, .size = 128, - .buf = calloc(128, sizeof(char *)) + .buf = xcalloc(128, sizeof(char *)) }; return vec; } @@ -47,7 +48,7 @@ struct string_vec string_vec_copy(struct string_vec *restrict vec) struct string_vec copy = { .count = vec->count, .size = vec->size, - .buf = calloc(vec->size, sizeof(char *)) + .buf = xcalloc(vec->size, sizeof(char *)) }; for (size_t i = 0; i < vec->count; i++) { @@ -61,7 +62,7 @@ void string_vec_add(struct string_vec *restrict vec, const char *restrict str) { if (vec->count == vec->size) { vec->size *= 2; - vec->buf = realloc(vec->buf, vec->size * sizeof(vec->buf[0])); + vec->buf = xrealloc(vec->buf, vec->size * sizeof(vec->buf[0])); } vec->buf[vec->count] = strdup(str); vec->count++; diff --git a/src/string_vec.h b/src/string_vec.h index b3395ad..7ebcb53 100644 --- a/src/string_vec.h +++ b/src/string_vec.h @@ -3,6 +3,11 @@ #include <stddef.h> +struct program { + char *name; + size_t run_count; +}; + struct string_vec { size_t count; size_t size; @@ -35,11 +35,10 @@ struct tofi { struct { struct surface surface; struct zwlr_layer_surface_v1 *zwlr_layer_surface; - struct image background_image; struct color background_color; struct entry entry; - int32_t width; - int32_t height; + uint32_t width; + uint32_t height; uint32_t scale; bool resize; } window; diff --git a/src/xmalloc.c b/src/xmalloc.c new file mode 100644 index 0000000..8a08cb8 --- /dev/null +++ b/src/xmalloc.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include "log.h" +#include "xmalloc.h" + +void *xmalloc(size_t size) +{ + void *ptr = malloc(size); + + if (ptr != NULL) { + log_debug("Allocated %zu bytes.\n", size); + return ptr; + } else { + fputs("Out of memory, exiting.", stderr); + exit(EXIT_FAILURE); + } +} + +void *xcalloc(size_t nmemb, size_t size) +{ + void *ptr = calloc(nmemb, size); + + if (ptr != NULL) { + log_debug("Allocated %zux%zu bytes.\n", nmemb, size); + return ptr; + } else { + fputs("Out of memory, exiting.", stderr); + exit(EXIT_FAILURE); + } +} + +void *xrealloc(void *ptr, size_t size) +{ + ptr = realloc(ptr, size); + + if (ptr != NULL) { + log_debug("Reallocated to %zu bytes.\n", size); + return ptr; + } else { + fputs("Out of memory, exiting.", stderr); + exit(EXIT_FAILURE); + } +} diff --git a/src/xmalloc.h b/src/xmalloc.h new file mode 100644 index 0000000..a661004 --- /dev/null +++ b/src/xmalloc.h @@ -0,0 +1,14 @@ +#ifndef XMALLOC_H +#define XMALLOC_H + +#include <stdlib.h> + +__attribute__((malloc)) +void *xmalloc(size_t size); + +__attribute__((malloc)) +void *xcalloc(size_t nmemb, size_t size); + +void *xrealloc(void *ptr, size_t size); + +#endif /* XMALLOC_H */ |