diff --git a/data/themes/default.edc b/data/themes/default.edc new file mode 100644 index 0000000..58a7b5d --- /dev/null +++ b/data/themes/default.edc @@ -0,0 +1,64 @@ + +collections +{ + group + { + name: "entice/core"; + images.image: "vg1.png" COMP; + + parts + { + // BACKGROUND + part + { + name: "bg"; + type: RECT; + mouse_events: 0; + description + { + state: "default" 0.0; + color: 64 64 64 255; + } + } + part + { + name: "vg1"; + mouse_events: 0; + description + { + state: "default" 0.0; + fixed: 1 1; + rel2.relative: 1.0 0.5; + image.normal: "vg1.png"; + color: 64 64 64 255; + fill + { + size.relative: 0.0 1.0; + size.offset: 256 0; + smooth: 0; + } + } + description + { + state: "focused" 0.0; + inherit: "default" 0.0; + color: 32 32 32 255; + } + } + program + { + signal: "state,win,focused"; + source: "entice"; + action: STATE_SET "focused" 0.0; + target: "vg1"; + } + program + { + signal: "state,win,unfocused"; + source: "entice"; + action: STATE_SET "default" 0.0; + target: "vg1"; + } + } + } +} \ No newline at end of file diff --git a/data/themes/images/vg1.png b/data/themes/images/vg1.png new file mode 100644 index 0000000..ab1dd07 Binary files /dev/null and b/data/themes/images/vg1.png differ diff --git a/data/themes/meson.build b/data/themes/meson.build new file mode 100644 index 0000000..7a54e58 --- /dev/null +++ b/data/themes/meson.build @@ -0,0 +1,19 @@ + +edc_files = [ + 'default.edc' +] + +foreach edc_file : edc_files + custom_target('edje_cc_' + edc_file, + input : edc_file, + depfile : '@BASENAME@.edj.d', + output : '@BASENAME@.edj', + command : edje_cc_exe + + [ + '-id', join_paths(meson.current_source_dir(), 'images'), + '@INPUT@', '@OUTPUT@' + ], + install : true, + install_dir : join_paths(dir_pkgdata, 'themes'), + ) +endforeach diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..3c4e923 --- /dev/null +++ b/meson.build @@ -0,0 +1,116 @@ +project('entice', 'c', + version : '0.0.1', + meson_version : '>= 0.53', + default_options : [ + 'warning_level=2', + 'buildtype=debugoptimized', + 'c_std=c99' + ] +) + +v_array = meson.project_version().split('.') +v_maj = v_array[0] +v_min = v_array[1] +v_mic = v_array[2] + +# install paths +dir_prefix = get_option('prefix') +dir_include = join_paths(dir_prefix, get_option('includedir')) +dir_pkginclude = join_paths(dir_include, meson.project_name()) +dir_bin = join_paths(dir_prefix, get_option('bindir')) +dir_lib = join_paths(dir_prefix, get_option('libdir')) +dir_data = join_paths(dir_prefix, get_option('datadir')) +dir_pkgdata = join_paths(dir_data, meson.project_name()) +dir_locale = join_paths(dir_prefix, get_option('localedir')) + +# host + +host_os = host_machine.system() +linux = ['linux'] +bsd = ['bsd', 'freebsd', 'dragonfly', 'netbsd', 'openbsd'] +osx = ['darwin'] +win32 = ['windows'] + +cygwin = ['cygwin'] +sys_linux = linux.contains(host_os) +sys_bsd = bsd.contains(host_os) +sys_windows = win32.contains(host_os) +sys_cygwin = cygwin.contains(host_os) +sys_osx = osx.contains(host_os) + +host_cpu = host_machine.cpu() + +# binaries + +cc = meson.get_compiler('c') + +entice_cflags = [] +entice_cflags_try = [ + '-Wshadow', + '-Wstrict-prototypes', + '-Werror=missing-prototypes', + '-Werror=pointer-arith', + '-Wno-missing-field-initializers' +] + +foreach cf: entice_cflags_try + if cc.has_argument(cf) == true + entice_cflags += cf + endif +endforeach +add_global_arguments(entice_cflags, language: 'c') + +pkgconfig = import('pkgconfig') +windows = import('windows') + +edje_cc = find_program('edje_cc', native: true) +edje_cc_exe = [ edje_cc ] + +# libraries + +config_dir = [include_directories('.')] + +efl_req = '>= 1.20' +entice_deps = [ dependency('elementary', version : efl_req) ] + +if get_option('nls') == true + entice_cargs = [ '-DGETTEXT_PACKAGE="entice"' ] + entice_deps += cc.find_library('intl', required: false) +endif + +# configuration + +config_h = configuration_data() +config_h.set_quoted('PACKAGE_NAME', meson.project_name()) +config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) +config_h.set_quoted('PACKAGE_BIN_DIR', dir_bin) +config_h.set_quoted('PACKAGE_LIB_DIR', dir_lib) +config_h.set_quoted('PACKAGE_DATA_DIR', dir_data) +config_h.set_quoted('LOCALE_DIR', dir_locale) + +subdir('src/bin') +subdir('data/themes') +if get_option('nls') == true + subdir('po') +endif + +# Use config_h after all subdirs have set values + +configure_file(output : 'config.h', configuration : config_h) + +summary({'OS': host_os, + 'NLS': get_option('nls') == true ? 'yes' : 'no', + }, section: 'Configuration Options Summary:') + +summary({'prefix': dir_prefix, + 'bindir': dir_bin, + 'libdir': dir_lib, + 'incdir': dir_include, + 'pkgincdir': dir_pkginclude, + 'datadir': dir_data, + 'pkgdatadir': dir_pkgdata, + }, section: 'Directories:') + +summary({'compilation': 'ninja', + 'installation': 'ninja install', + }, section: 'Compilation') \ No newline at end of file diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..d48dc63 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,6 @@ + +option('nls', + type: 'boolean', + value: true, + description: 'enable localization: (default=true)' +) diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 0000000..e69de29 diff --git a/src/bin/entice_config.c b/src/bin/entice_config.c new file mode 100644 index 0000000..638499f --- /dev/null +++ b/src/bin/entice_config.c @@ -0,0 +1,234 @@ + +#include + +#include + +#include "entice_private.h" +#include "entice_config.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +#define ENTICE_CONFIG_EDD_KEY_ADD(_s, _m, _t) \ + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_keys, Entice_Config_Keys, _s, _m, _t) + +#define ADD_KEYS(Name, Ctrl, Alt, Shift, Win, Cb) \ + kb = calloc(1, sizeof(Entice_Config_Keys)); \ + if (!kb) return; \ + kb->keyname = eina_stringshare_add_length(Name, strlen(Name)); \ + kb->ctrl = Ctrl; \ + kb->alt = Alt; \ + kb->shift = Shift; \ + kb->win = Win; \ + kb->cb = eina_stringshare_add_length(Cb, strlen(Cb)); \ + config->keys = eina_list_append(config->keys, kb) + +static Eet_Data_Descriptor *edd_base = NULL; +static Eet_Data_Descriptor *edd_keys = NULL; + +static void +_entice_default_keys_add(Entice_Config *config) +{ + Entice_Config_Keys *kb; + + ADD_KEYS("F11", 0, 0, 0, 0, "win_fullscreen"); +} + +static Entice_Config * +_entice_config_new(void) +{ + Entice_Config *config; + + config = (Entice_Config *)calloc(1, sizeof(Entice_Config)); + if (!config) + return NULL; + + config->theme = eina_stringshare_add("default.edj"); + config->cg_width = 480; + config->cg_height = 640; + config->custom_geometry = EINA_FALSE; + config->disable_visual_bell = EINA_FALSE; + config->bell_rings = EINA_TRUE; + _entice_default_keys_add(config); + + return config; +} + +static const char * +_entice_config_theme_path_get(const char *name) +{ + static char path1[PATH_MAX]; + static char path2[PATH_MAX]; + struct stat s; + + snprintf(path2, sizeof(path2) - 1, "%s/.entice/themes/%s", + eina_environment_home_get(), name); + if (stat(path2, &s) == 0) + return path2; + snprintf(path1, sizeof(path1) - 1, "%s/entice/themes/%s", + elm_app_data_dir_get(), name); + return path1; +} + +/*============================================================================* + * Global * + *============================================================================*/ + +void +entice_config_init(void) +{ + char path[PATH_MAX]; + Eet_Data_Descriptor_Class eddc; + Eet_Data_Descriptor_Class eddkc; + + snprintf(path, sizeof(path), "%s/.entice/themes", + eina_environment_home_get()); + ecore_file_mkpath(path); + + eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc), + "Config", sizeof(Entice_Config)); + edd_base = eet_data_descriptor_stream_new(&eddc); + + eet_eina_stream_data_descriptor_class_set(&eddkc, sizeof(eddkc), + "Config_Keys", sizeof(Entice_Config_Keys)); + edd_keys = eet_data_descriptor_stream_new(&eddkc); + + ENTICE_CONFIG_EDD_KEY_ADD("keyname", keyname, EET_T_STRING); + ENTICE_CONFIG_EDD_KEY_ADD("ctrl", ctrl, EET_T_UCHAR); + ENTICE_CONFIG_EDD_KEY_ADD("alt", alt, EET_T_UCHAR); + ENTICE_CONFIG_EDD_KEY_ADD("shift", shift, EET_T_UCHAR); + ENTICE_CONFIG_EDD_KEY_ADD("win", win, EET_T_UCHAR); + ENTICE_CONFIG_EDD_KEY_ADD("meta", meta, EET_T_UCHAR); + ENTICE_CONFIG_EDD_KEY_ADD("hyper", hyper, EET_T_UCHAR); + ENTICE_CONFIG_EDD_KEY_ADD("cb", cb, EET_T_STRING); + + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_base, Entice_Config, "theme", theme, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_base, Entice_Config, "cg_width", cg_width, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_base, Entice_Config, "cg_height", cg_height, EET_T_INT); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_base, Entice_Config, "custom_geometry", custom_geometry, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_base, Entice_Config, "disable_visual_bell", disable_visual_bell, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_BASIC(edd_base, Entice_Config, "bell_rings", bell_rings, EET_T_UCHAR); + EET_DATA_DESCRIPTOR_ADD_LIST(edd_base, Entice_Config, "keys", keys, edd_keys); +} + +void +entice_config_shutdown(void) +{ + eet_data_descriptor_free(edd_base); + eet_data_descriptor_free(edd_keys); +} + +Entice_Config * +entice_config_load(const char *key) +{ + char buf[PATH_MAX]; + Eet_File *ef; + Entice_Config *config = NULL; + + EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL); + + snprintf(buf, sizeof(buf), "%s/.entice/config/base.cfg", + eina_environment_home_get()); + buf[sizeof(buf) - 1] = '\0'; + ef = eet_open(buf, EET_FILE_MODE_READ); + if (ef) + { + config = eet_data_read(ef, edd_base, key); + eet_close(ef); + if (eina_list_count(config->keys) == 0) + { + _entice_default_keys_add(config); + } + } + + if (!config) + config = _entice_config_new(); + + if (config) + config->config_key = eina_stringshare_add(key); /* not in eet */ + + return config; +} + +void +entice_config_del(Entice_Config *config) +{ + Entice_Config_Keys *key; + + if (!config) + return; + + eina_stringshare_del(config->theme); + + EINA_LIST_FREE(config->keys, key) + { + eina_stringshare_del(key->keyname); + eina_stringshare_del(key->cb); + free(key); + } + + eina_stringshare_del(config->config_key); + free(config); +} + +void +entice_config_save(Entice_Config *config, const char *key) +{ + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + Eet_File *ef; + + EINA_SAFETY_ON_NULL_RETURN(config); + + if (!key) key = config->config_key; + snprintf(buf, sizeof(buf), "%s/.entice/config", + eina_environment_home_get()); + ecore_file_mkpath(buf); + snprintf(buf, sizeof(buf), "%s/.entice/config/base.cfg.tmp", + eina_environment_home_get()); + snprintf(buf2, sizeof(buf2), "%s/.entice/config/base.cfg", + eina_environment_home_get()); + ef = eet_open(buf, EET_FILE_MODE_WRITE); + if (ef) + { + int ok; + + ok = eet_data_write(ef, edd_base, key, config, 1); + eet_close(ef); + if (ok) ecore_file_mv(buf, buf2); + } +} + +const char * +entice_config_theme_path_get(const Entice_Config *config) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(config, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(config->theme, NULL); + + if (strchr(config->theme, '/')) + return config->theme; + + return _entice_config_theme_path_get(config->theme); +} + +const char * +entice_config_theme_path_default_get(const Entice_Config *config) +{ + static char path[PATH_MAX]; + + EINA_SAFETY_ON_NULL_RETURN_VAL(config, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(config->theme, NULL); + + *path = '\0'; + if (path[0]) return path; + + snprintf(path, sizeof(path), "%s/entice/themes/default.edj", + elm_app_data_dir_get()); + + return path; +} + +/*============================================================================* + * API * + *============================================================================*/ diff --git a/src/bin/entice_config.h b/src/bin/entice_config.h new file mode 100644 index 0000000..ca67ebb --- /dev/null +++ b/src/bin/entice_config.h @@ -0,0 +1,41 @@ +#ifndef ENTICE_CONFIG_H +#define ENTICE_CONFIG_H + +typedef struct Entice_Config_Keys_ Entice_Config_Keys; +typedef struct Entice_Config_ Entice_Config; + +struct Entice_Config_Keys_ +{ + const char *keyname; + Eina_Bool ctrl; + Eina_Bool alt; + Eina_Bool shift; + Eina_Bool win; + Eina_Bool meta; + Eina_Bool hyper; + const char *cb; +}; + +struct Entice_Config_ +{ + const char *theme; + int cg_width; + int cg_height; + Eina_Bool custom_geometry; + Eina_Bool disable_visual_bell; + Eina_Bool bell_rings; + Eina_List *keys; + + const char *config_key; +}; + +void entice_config_init(void); +void entice_config_shutdown(void); +Entice_Config *entice_config_load(const char *key); +void entice_config_del(Entice_Config *config); +void entice_config_save(Entice_Config *config, const char *key); + +const char *entice_config_theme_path_get(const Entice_Config *config); +const char *entice_config_theme_path_default_get(const Entice_Config *config); + +#endif /* ENTICE_CONFIG_H */ diff --git a/src/bin/entice_main.c b/src/bin/entice_main.c new file mode 100644 index 0000000..b59b4a3 --- /dev/null +++ b/src/bin/entice_main.c @@ -0,0 +1,251 @@ + +#include + +#include +#include + +#include "entice_private.h" +#include "entice_config.h" +#include "entice_win.h" + +#define ENTICE_COPYRIGHT "(C) 2021 Vincent Torri and others" + +static Ecore_Getopt options = { + PACKAGE_NAME, + "%prog [options] [filename]", + PACKAGE_VERSION, + gettext_noop(ENTICE_COPYRIGHT), + "BSD 2-Clause License", + gettext_noop("Simple image viewer written with Enlightenment Foundation Libraries."), + EINA_TRUE, + { + ECORE_GETOPT_STORE_TRUE('f', "fullscreen", + gettext_noop("Go into the fullscreen mode from start.")), + + ECORE_GETOPT_VERSION ('V', "version"), + ECORE_GETOPT_COPYRIGHT ('C', "copyright"), + ECORE_GETOPT_LICENSE ('L', "license"), + ECORE_GETOPT_HELP ('h', "help"), + ECORE_GETOPT_SENTINEL + } +}; + +int entice_app_log_dom_global = 1; + +#if ENABLE_NLS +static void +_entice_translate_options(void) +{ + Ecore_Getopt_Desc *desc; + + options.copyright = eina_stringshare_printf(_(options.copyright), + 2020); + + desc = (Ecore_Getopt_Desc *)options.descs; + while ((desc->shortname != '\0') || + (desc->longname) || + (desc->action == ECORE_GETOPT_ACTION_CATEGORY)) + { + if (desc->help) + { + switch (desc->action) + { + case ECORE_GETOPT_ACTION_VERSION: + desc->help = _("show program version."); + break; + case ECORE_GETOPT_ACTION_COPYRIGHT: + desc->help = _("show copyright."); + break; + case ECORE_GETOPT_ACTION_LICENSE: + desc->help = _("show license."); + break; + case ECORE_GETOPT_ACTION_HELP: + desc->help = _("show this message."); + break; + default: + desc->help = _(desc->help); + } + } + desc++; + } +} +#endif + +static Eina_List * +_file_list_append(Eina_List *list, const char *path) +{ + const Eina_List *l; + const char *mime; + const char *data; + Eina_Bool found; + + mime = efreet_mime_type_get(path); + if (mime && + (strncmp(mime, "image/", strlen("image/")) == 0)) + { + found = EINA_FALSE; + EINA_LIST_FOREACH(list, l, data) + { + if (strcmp(data, path) == 0) + { + found = EINA_TRUE; + break; + } + } + if (!found) + list = eina_list_append(list, eina_stringshare_add(path)); + } + + return list; +} + + +static Eina_List * +_dir_parse(Eina_List *list, const char *path) +{ + Eina_Iterator *it; + Eina_File_Direct_Info *info; + + if (!path || !*path) + return list; + + it = eina_file_stat_ls(path); + EINA_ITERATOR_FOREACH(it, info) + { + if (info->type == EINA_FILE_REG) + { + list = _file_list_append(list, info->path); + } + } + fflush(stdout); + + return list; +} + +static EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Evas_Object *win; + Eina_List *list; + Eina_Bool fullscreen = EINA_FALSE; + Eina_Bool quit_option = EINA_FALSE; + Ecore_Getopt_Value values[] = { + ECORE_GETOPT_VALUE_BOOL(fullscreen), + + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + ECORE_GETOPT_VALUE_BOOL(quit_option), + + ECORE_GETOPT_VALUE_NONE + }; + int args; + + elm_need_efreet(); + + entice_app_log_dom_global = eina_log_domain_register(PACKAGE_NAME, NULL); + if (entice_app_log_dom_global < 0) + { + EINA_LOG_CRIT(_("could not create log domain '" PACKAGE_NAME "'.")); + goto end; + } + + args = ecore_getopt_parse(&options, values, argc, argv); + if (args < 0) + { + ERR(_("Could not parse command line options.")); + goto end; + } + + if (quit_option) + goto end; + + list = NULL; + if (args == argc) + { + list = _dir_parse(list, efreet_pictures_dir_get()); + } + else + { + int i; + char *realpath; + + for (i = args; i < argc; i++) + { + realpath = strdup(argv[i]); + if (!strncasecmp(realpath, "file://", strlen("file://"))) + { + Efreet_Uri *uri = efreet_uri_decode(realpath); + if (uri) + { + free(realpath); + realpath = ecore_file_realpath(uri->path); + efreet_uri_free(uri); + } + } + if (ecore_file_is_dir(realpath)) + list = _dir_parse(list, realpath); + else + { + list = _file_list_append(list, realpath); + free(realpath); + } + } + } + { + Eina_List *l; + char *data; + + EINA_LIST_FOREACH(list, l, data) + { + printf(" ** %s\n", data); + } + } + + entice_config_init(); + /* FIXME key binding */ + + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + elm_app_compile_bin_dir_set(PACKAGE_BIN_DIR); + elm_app_compile_lib_dir_set(PACKAGE_LIB_DIR); + elm_app_compile_data_dir_set(PACKAGE_DATA_DIR); +#if ENABLE_NLS + elm_app_compile_locale_set(LOCALEDIR); +#endif + elm_app_name_set(PACKAGE_NAME); + elm_app_info_set(elm_main, PACKAGE_NAME, "themes/default.edj"); + +#if ENABLE_NLS + bindtextdomain(PACKAGE_NAME, elm_app_locale_dir_get()); + textdomain(PACKAGE_NAME); + _entice_translate_options(); +#else + options.copyright = ENTICE_COPYRIGHT; +#endif + + win = entice_win_add(); + if (!win) + { + ERR(_("could not create main window.")); + goto shutdown_config; + } + evas_object_resize(win, + 562 * elm_config_scale_get(), + 800 * elm_config_scale_get()); + + evas_object_show(win); + + if (fullscreen) elm_win_fullscreen_set(win, EINA_TRUE); + + elm_run(); + + return 0; + + shutdown_config: + entice_config_shutdown(); + eina_log_domain_unregister(entice_app_log_dom_global); + entice_app_log_dom_global = -1; + end: + return 1; +} +ELM_MAIN() diff --git a/src/bin/entice_private.h b/src/bin/entice_private.h new file mode 100644 index 0000000..a5055d5 --- /dev/null +++ b/src/bin/entice_private.h @@ -0,0 +1,44 @@ +#ifndef ENTICE_PRIVATE_H +#define ENTICE_PRIVATE_H + +#if ENABLE_NLS +# include +# define _(string) gettext(string) +#else +# define _(string) (string) +#endif +#define gettext_noop(String) String + +extern int entice_app_log_dom_global; + +#ifdef ENTICE_DEFAULT_LOG_COLOR +# undef ENTICE_DEFAULT_LOG_COLOR +#endif +#define ENTICE_DEFAULT_LOG_COLOR EINA_COLOR_CYAN + +#ifdef ERR +# undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(entice_app_log_dom_global, __VA_ARGS__) + +#ifdef DBG +# undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(entice_app_log_dom_global, __VA_ARGS__) + +#ifdef INF +# undef INF +#endif +#define INF(...) EINA_LOG_DOM_INFO(entice_app_log_dom_global, __VA_ARGS__) + +#ifdef WRN +# undef WRN +#endif +#define WRN(...) EINA_LOG_DOM_WARN(entice_app_log_dom_global, __VA_ARGS__) + +#ifdef CRIT +# undef CRIT +#endif +#define CRIT(...) EINA_LOG_DOM_CRIT(entice_app_log_dom_global, __VA_ARGS__) + +#endif /* ENTICE_PRIVATE_H */ diff --git a/src/bin/entice_theme.c b/src/bin/entice_theme.c new file mode 100644 index 0000000..a4b732b --- /dev/null +++ b/src/bin/entice_theme.c @@ -0,0 +1,92 @@ + +#include + +#include + +#include "entice_private.h" +#include "entice_config.h" +#include "entice_win.h" +#include "entice_theme.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +static char *entice_theme_default_get(Entice *entice); + +static void +_entice_theme_reload_cb(void *data EINA_UNUSED, Evas_Object *obj, const char *emission EINA_UNUSED, const char *source EINA_UNUSED) +{ + void (*func)(void *d); + void *func_data; + const char *file; + const char *group; + + edje_object_file_get(obj, &file, &group); + edje_object_file_set(obj, file, group); + func = evas_object_data_get(obj, "theme_reload_func"); + func_data = evas_object_data_get(obj, "theme_reload_func_data"); + if (func) func(func_data); +} + +static char * +entice_theme_default_get(Entice *entice) +{ + int size; + + if (entice->theme_file) + return entice->theme_file; + + size = snprintf(NULL, 0, + "%s/entice/themes/default.edj", elm_app_data_dir_get()); + entice->theme_file = (char *)malloc(size + 2); + if (!entice->theme_file) + return NULL; + + snprintf(entice->theme_file, size + 1, + "%s/entice/themes/default.edj", elm_app_data_dir_get()); + + return entice->theme_file; +} + +/*============================================================================* + * Global * + *============================================================================*/ + +Eina_Bool +entice_theme_apply(Evas_Object *win, const char *group) +{ + Entice *entice; + + if ((!win) || (!group)) + return EINA_FALSE; + + entice = evas_object_data_get(win, "entice"); + if (!entice) + return EINA_FALSE; + + if (elm_layout_file_set(entice->layout, entice_theme_default_get(entice), group)) + return EINA_TRUE; + + return EINA_FALSE; +} + +void +entice_theme_reload(Evas_Object *win) +{ + Entice *entice; + + if (!win) + return; + + entice = evas_object_data_get(win, "entice"); + if (!entice) + return; + + edje_object_signal_callback_add(entice->layout, "edje,change,file", "edje", + _entice_theme_reload_cb, NULL); +} + +/*============================================================================* + * API * + *============================================================================*/ diff --git a/src/bin/entice_theme.h b/src/bin/entice_theme.h new file mode 100644 index 0000000..82a5eeb --- /dev/null +++ b/src/bin/entice_theme.h @@ -0,0 +1,9 @@ +#ifndef ENTICE_THEME_H +#define ENTICE_THEME_H + + +Eina_Bool entice_theme_apply(Evas_Object *win, const char *group); +void entice_theme_reload(Evas_Object *win); + + +#endif /* ENTICE_THEME_H */ diff --git a/src/bin/entice_win.c b/src/bin/entice_win.c new file mode 100644 index 0000000..f605644 --- /dev/null +++ b/src/bin/entice_win.c @@ -0,0 +1,216 @@ + + +#include + +#include + +#include "entice_private.h" +#include "entice_config.h" +#include "entice_theme.h" +#include "entice_win.h" + +/*============================================================================* + * Local * + *============================================================================*/ + +static void +_cb_key_down(void *data, + Evas *evas EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info) +{ + Evas_Event_Key_Down *ev; + Evas_Object *win; + Eina_Bool ctrl, alt, shift, winm, meta, hyper; /* modifiers */ + + EINA_SAFETY_ON_NULL_RETURN(event_info); + + ev = (Evas_Event_Key_Down *)event_info; + win = (Evas_Object *)data; + + ctrl = evas_key_modifier_is_set(ev->modifiers, "Control"); + alt = evas_key_modifier_is_set(ev->modifiers, "Alt"); + shift = evas_key_modifier_is_set(ev->modifiers, "Shift"); + winm = evas_key_modifier_is_set(ev->modifiers, "Super"); + meta = + evas_key_modifier_is_set(ev->modifiers, "Meta") || + evas_key_modifier_is_set(ev->modifiers, "AltGr") || + evas_key_modifier_is_set(ev->modifiers, "ISO_Level3_Shift"); + hyper = evas_key_modifier_is_set(ev->modifiers, "Hyper"); + + /* No modifier */ + if (!ctrl && !alt && !shift && !winm && !meta && !hyper) + { + if (!strcmp(ev->keyname, "F11")) + { + elm_win_fullscreen_set(win, !elm_win_fullscreen_get(win)); + } + } + + /* Control modifier */ + if (ctrl && !alt && !shift && !winm && !meta && !hyper) + { + if (!strcmp(ev->keyname, "q")) + { + evas_object_del(win); + } + } +} + +static void +_cb_win_del(void *data EINA_UNUSED, + Evas *_e EINA_UNUSED, + Evas_Object *win, + void *_event EINA_UNUSED) +{ + Entice *entice; + + entice = evas_object_data_get(win, "entice"); + entice_config_del(entice->config); + evas_object_data_del(win, "entice"); + free(entice); +} + +static void +_cb_fullscreen(void *data EINA_UNUSED, Evas_Object *win, void *event EINA_UNUSED) +{ + Entice *entice; + + entice = evas_object_data_get(win, "entice"); + elm_layout_signal_emit(entice->layout, "state,win,fullscreen", "entice"); + elm_win_noblank_set(win, EINA_TRUE); +} + +static void +_cb_unfullscreen(void *data EINA_UNUSED, Evas_Object *win, void *event EINA_UNUSED) +{ + Entice *entice; + + entice = evas_object_data_get(win, "entice"); + if (!elm_win_fullscreen_get(win)) + { + elm_layout_signal_emit(entice->layout, "state,win,normal", "entice"); + elm_win_noblank_set(win, EINA_FALSE); + } +} + +static void +_cb_focused(void *data EINA_UNUSED, Evas_Object *win, void *event EINA_UNUSED) +{ + Entice *entice; + + entice = evas_object_data_get(win, "entice"); + elm_layout_signal_emit(entice->layout, "state,win,focused", "entice"); +} + +static void +_cb_unfocused(void *data EINA_UNUSED, Evas_Object *win, void *event EINA_UNUSED) +{ + Entice *entice; + + entice = evas_object_data_get(win, "entice"); + elm_layout_signal_emit(entice->layout, "state,win,unfocused", "entice"); +} + +/*============================================================================* + * Global * + *============================================================================*/ + +Evas_Object * +entice_win_add(void) +{ + Evas_Object *win; + Evas_Object *o; + Entice *entice; + + entice = (Entice *)calloc(1, sizeof(Entice)); + if (!entice) + { + ERR(_("could not allocate memory for Entice struct")); + return NULL; + } + + entice->config = entice_config_load("config"); + if (!entice->config) + { + ERR(_("could not load \"config\" configuration.")); + free(entice); + return NULL; + } + elm_theme_overlay_add(NULL, entice_config_theme_path_default_get(entice->config)); + elm_theme_overlay_add(NULL, entice_config_theme_path_get(entice->config)); + + /* main window */ + win = elm_win_add(NULL, PACKAGE_NAME, ELM_WIN_BASIC); + if (!win) + { + ERR(_("could not create elm window.")); + entice_config_del(entice->config); + free(entice); + return NULL; + } + + elm_win_title_set(win, "Entice"); + /* TODO: icon name */ + elm_win_autodel_set(win, EINA_TRUE); + elm_win_focus_highlight_enabled_set(win, EINA_TRUE); + + evas_object_data_set(win, "entice", entice); + + evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _cb_win_del, entice); + + evas_object_smart_callback_add(win, "fullscreen", _cb_fullscreen, NULL); + evas_object_smart_callback_add(win, "unfullscreen", _cb_unfullscreen, NULL); + evas_object_smart_callback_add(win, "focused", _cb_focused, entice); + evas_object_smart_callback_add(win, "unfocused", _cb_unfocused, entice); + + /* conformant */ + o = elm_conformant_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_win_resize_object_add(win, o); + evas_object_show(o); + entice->conform = o; + + /* gui layout */ + o = elm_layout_add(win); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_fill_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_content_set(entice->conform, o); + evas_object_repeat_events_set(o, EINA_FALSE); + evas_object_show(o); + entice->layout = o; + if (!entice_theme_apply(win, "entice/core")) + { + ERR(_("could not apply the theme.")); + _cb_win_del(NULL, NULL, win, NULL); + return NULL; + } + + /* dummy button to catch mouse events */ + o = elm_button_add(win); + elm_object_focus_allow_set(o, EINA_FALSE); + elm_object_focus_move_policy_set(o, ELM_FOCUS_MOVE_POLICY_CLICK); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, o); + evas_object_color_set(o, 0, 0, 0, 0); + evas_object_repeat_events_set(o, EINA_TRUE); + evas_object_show(o); + /* evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, */ + /* _cb_mouse_down, win); */ + entice->event_mouse = o; + + /* dummy button to catch keyboard events */ + o = elm_button_add(win); + elm_object_focus_highlight_style_set(o, "blank"); + evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, o); + evas_object_lower(o); + evas_object_show(o); + elm_object_focus_set(o, EINA_TRUE); + evas_object_event_callback_add(o, EVAS_CALLBACK_KEY_DOWN, + _cb_key_down, win); + entice->event_kbd = o; + + return win; +} diff --git a/src/bin/entice_win.h b/src/bin/entice_win.h new file mode 100644 index 0000000..67f295d --- /dev/null +++ b/src/bin/entice_win.h @@ -0,0 +1,25 @@ +#ifndef ENTICE_WIN_H +#define ENTICE_WIN_H + +typedef struct Entice Entice; + +struct Entice +{ + /* window content */ + Evas_Object *conform; + Evas_Object *layout; + Evas_Object *event_mouse; + Evas_Object *event_kbd; + Eina_Bool focused; + + /* list of opened documents */ + Eina_List *docs; + + /* theme */ + Entice_Config *config; + char *theme_file; +}; + +Evas_Object *entice_win_add(void); + +#endif /* ENTICE_WIN_H */ diff --git a/src/bin/meson.build b/src/bin/meson.build new file mode 100644 index 0000000..29ecf87 --- /dev/null +++ b/src/bin/meson.build @@ -0,0 +1,19 @@ + +entice_bin_src = [ + 'entice_config.c', + 'entice_main.c', + 'entice_theme.c', + 'entice_win.c' +] + +# Windows resource file + +## todo + + +entice_bin = executable('entice', entice_bin_src, + c_args : [ entice_cargs ], + dependencies : [ entice_deps ], + include_directories : config_dir, + install : true +)