From ac3a59a0d16a90e1b7fb076ae1cb5b0a51f16f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 14 Nov 2011 22:43:37 -0500 Subject: [PATCH] window: Add a cheesy parser for ini-files, use it in desktop-shell --- clients/Makefile.am | 3 +- clients/config.c | 137 ++++++++++++++++++++++++++++++++++++++++ clients/desktop-shell.c | 80 ++++++++++++++++------- clients/window.h | 23 +++++++ 4 files changed, 219 insertions(+), 24 deletions(-) create mode 100644 clients/config.c diff --git a/clients/Makefile.am b/clients/Makefile.am index 9c14eb93..bae9f3f0 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -38,7 +38,8 @@ libtoytoolkit_a_SOURCES = \ window.c \ window.h \ cairo-util.c \ - cairo-util.h + cairo-util.h \ + config.c toolkit_libs = \ libtoytoolkit.a \ diff --git a/clients/config.c b/clients/config.c new file mode 100644 index 00000000..f389b69a --- /dev/null +++ b/clients/config.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +static int +handle_key(const struct config_key *key, const char *value) +{ + char *end, *s; + int i, len; + + switch (key->type) { + case CONFIG_KEY_INTEGER: + i = strtol(value, &end, 0); + if (*end != '\n') { + fprintf(stderr, "invalid integer: %s\n", value); + return -1; + } + *(int *)key->data = i; + return 0; + + case CONFIG_KEY_STRING: + len = strlen(value); + s = malloc(len); + if (s == NULL) + return -1; + memcpy(s, value, len - 1); + s[len - 1] = '\0'; + *(char **)key->data = s; + return 0; + + case CONFIG_KEY_BOOL: + if (strcmp(value, "false") == 0) + *(int *)key->data = 0; + else if (strcmp(value, "true") == 0) + *(int *)key->data = 1; + else { + fprintf(stderr, "invalid bool: %s\n", value); + return -1; + } + return 0; + + default: + assert(0); + break; + } +} + +int +parse_config_file(const char *path, + const struct config_section *sections, int num_sections, + void *data) +{ + FILE *fp; + char line[512], *p; + const struct config_section *current = NULL; + int i; + + fp = fopen(path, "r"); + if (fp == NULL) { + fprintf(stderr, "couldn't open %s\n", path); + return -1; + } + + while (fgets(line, sizeof line, fp)) { + if (line[0] == '#' || line[0] == '\n') { + continue; + } if (line[0] == '[') { + p = strchr(&line[1], ']'); + if (!p || p[1] != '\n') { + fprintf(stderr, "malformed " + "section header: %s\n", line); + fclose(fp); + return -1; + } + if (current && current->done) + current->done(data); + p[0] = '\0'; + for (i = 0; i < num_sections; i++) { + if (strcmp(sections[i].name, &line[1]) == 0) { + current = §ions[i]; + break; + } + } + if (i == num_sections) + current = NULL; + } else if (p = strchr(line, '='), p != NULL) { + if (current == NULL) + continue; + p[0] = '\0'; + for (i = 0; i < current->num_keys; i++) { + if (strcmp(current->keys[i].name, line) == 0) { + if (handle_key(¤t->keys[i], &p[1]) < 0) { + fclose(fp); + return -1; + } + break; + } + } + } else { + fprintf(stderr, "malformed config line: %s\n", line); + fclose(fp); + return -1; + } + } + + if (current && current->done) + current->done(data); + + fclose(fp); + + return 0; +} diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c index b9157238..33ea677f 100644 --- a/clients/desktop-shell.c +++ b/clients/desktop-shell.c @@ -58,6 +58,30 @@ struct panel_item { const char *path; }; +static char *key_background_image; +static uint32_t key_panel_color; +static char *key_launcher_icon; +static char *key_launcher_path; +static void launcher_section_done(void *data); + +static const struct config_key shell_config_keys[] = { + { "background-image", CONFIG_KEY_STRING, &key_background_image }, + { "panel-color", CONFIG_KEY_INTEGER, &key_panel_color }, +}; + +static const struct config_key launcher_config_keys[] = { + { "icon", CONFIG_KEY_STRING, &key_launcher_icon }, + { "path", CONFIG_KEY_STRING, &key_launcher_path }, +}; + +static const struct config_section config_sections[] = { + { "wayland-desktop-shell", + shell_config_keys, ARRAY_LENGTH(shell_config_keys) }, + { "launcher", + launcher_config_keys, ARRAY_LENGTH(launcher_config_keys), + launcher_section_done } +}; + static void sigchild_handler(int s) { @@ -137,6 +161,16 @@ panel_draw_item(struct item *item, void *data) cairo_translate(cr, width + 10, 0); } +static void +set_hex_color(cairo_t *cr, uint32_t color) +{ + cairo_set_source_rgba(cr, + ((color >> 16) & 0xff) / 255.0, + ((color >> 8) & 0xff) / 255.0, + ((color >> 0) & 0xff) / 255.0, + ((color >> 24) & 0xff) / 255.0); +} + static void panel_redraw_handler(struct window *window, void *data) { @@ -147,7 +181,7 @@ panel_redraw_handler(struct window *window, void *data) surface = window_get_surface(window); cr = cairo_create(surface); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 0.9); + set_hex_color(cr, key_panel_color); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); @@ -294,28 +328,26 @@ global_handler(struct wl_display *display, uint32_t id, } } -static const struct { - const char *icon; - const char *path; -} launchers[] = { - { - "/usr/share/icons/gnome/24x24/apps/utilities-terminal.png", - "/usr/bin/gnome-terminal" - }, - { - "/usr/share/icons/gnome/24x24/apps/utilities-terminal.png", - "./clients/terminal" - }, - { - "/usr/share/icons/hicolor/24x24/apps/google-chrome.png", - "/usr/bin/google-chrome" - }, -}; +static void +launcher_section_done(void *data) +{ + struct desktop *desktop = data; + + if (key_launcher_icon == NULL || key_launcher_path == NULL) { + fprintf(stderr, "invalid launcher section\n"); + return; + } + + panel_add_item(desktop->panel, key_launcher_icon, key_launcher_path); + free(key_launcher_icon); + key_launcher_icon = NULL; + free(key_launcher_path); + key_launcher_path = NULL; +} int main(int argc, char *argv[]) { struct desktop desktop; - int i; desktop.display = display_create(&argc, &argv, NULL); if (desktop.display == NULL) { @@ -331,9 +363,11 @@ int main(int argc, char *argv[]) desktop.panel = panel_create(desktop.display); - for (i = 0; i < ARRAY_LENGTH(launchers); i++) - panel_add_item(desktop.panel, - launchers[i].icon, launchers[i].path); + parse_config_file("wayland-desktop-shell.ini", + config_sections, ARRAY_LENGTH(config_sections), + &desktop); + + printf("panel color: %08x\n", key_panel_color); desktop_shell_set_panel(desktop.shell, window_get_wl_surface(desktop.panel->window)); @@ -341,7 +375,7 @@ int main(int argc, char *argv[]) desktop.background = window_create(desktop.display, 0, 0); window_set_decoration(desktop.background, 0); window_set_custom(desktop.background); - desktop.background_path = argv[1]; + desktop.background_path = key_background_image; desktop_shell_set_background(desktop.shell, window_get_wl_surface(desktop.background)); diff --git a/clients/window.h b/clients/window.h index 290c6b91..40bf1026 100644 --- a/clients/window.h +++ b/clients/window.h @@ -322,5 +322,28 @@ input_offers_mime_type(struct input *input, const char *type); void input_receive_mime_type(struct input *input, const char *type, int fd); +enum { + CONFIG_KEY_INTEGER, + CONFIG_KEY_STRING, + CONFIG_KEY_BOOL +}; + +struct config_key { + const char *name; + int type; + void *data; +}; + +struct config_section { + const char *name; + const struct config_key *keys; + int num_keys; + void (*done)(void *data); +}; + +int +parse_config_file(const char *path, + const struct config_section *sections, int num_sections, + void *data); #endif