From ee80fe052f65b7c8281d4a8b3fe50225e091f111 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 2 Feb 2020 18:57:26 -0500 Subject: [PATCH] init: Add an API level concept to `capi`. The API level concept is something used by other projects such as Android and iOS to allow deprecated features to be removed and the bahavior to be altered without breaking compability with existing code. The same will apply to AwesomeWM. The current API level is "4" and as long as config use this, no deprecation or bahavior change will be exposed. If the user sets it to an higher value or we release the next major version and new users start to use the, then current, default config, they will use the new API level. The the far future, if ever, we could fork the entire Lua libraries to support legacy APIs. This would only require to keep the core API support for those legacy calls. In the meantime, `gears.debug` will use this to manage the deprecation and some conditional code will be added as a last resort attempt to preserve behavior compatibility while moving forward with breaking changes. --- awesome-version-internal.h | 1 + awesome.c | 1 + awesomeConfig.cmake | 2 + common/version.c | 7 +++ common/version.h | 1 + globalconf.h | 2 + luaa.c | 37 +++++++++++++++- options.c | 76 +++++++++++++++++++++++--------- tests/examples/shims/awesome.lua | 3 +- 9 files changed, 106 insertions(+), 24 deletions(-) diff --git a/awesome-version-internal.h b/awesome-version-internal.h index 173c2d3cf..395d143d7 100644 --- a/awesome-version-internal.h +++ b/awesome-version-internal.h @@ -3,6 +3,7 @@ #define AWESOME_VERSION "@AWESOME_VERSION@" #define AWESOME_RELEASE "@AWESOME_RELEASE@" +#define AWESOME_API_LEVEL @AWESOME_API_LEVEL@ #endif //_AWE_VERSION_INTERNAL_H_ diff --git a/awesome.c b/awesome.c index ba9c81517..c71699d91 100644 --- a/awesome.c +++ b/awesome.c @@ -580,6 +580,7 @@ main(int argc, char **argv) globalconf.keygrabber = LUA_REFNIL; globalconf.mousegrabber = LUA_REFNIL; globalconf.exit_code = EXIT_SUCCESS; + globalconf.api_level = awesome_default_api_level(); buffer_init(&globalconf.startup_errors); string_array_init(&searchpath); diff --git a/awesomeConfig.cmake b/awesomeConfig.cmake index 4592001c0..3cf42b11b 100644 --- a/awesomeConfig.cmake +++ b/awesomeConfig.cmake @@ -271,6 +271,7 @@ else() set(AWESOME_MAN_PATH ${CMAKE_INSTALL_PREFIX}/share/man CACHE PATH "awesome manpage directory") endif() + # Hide to avoid confusion mark_as_advanced(CMAKE_INSTALL_CMAKE_INSTALL_PREFIX) @@ -280,6 +281,7 @@ set(AWESOME_SYSCONFDIR ${XDG_CONFIG_DIR}/${PROJECT_AWE_NAME}) set(AWESOME_LUA_LIB_PATH ${AWESOME_DATA_PATH}/lib) set(AWESOME_ICON_PATH ${AWESOME_DATA_PATH}/icons) set(AWESOME_THEMES_PATH ${AWESOME_DATA_PATH}/themes) +set(AWESOME_API_LEVEL 4) # }}} if(GENERATE_DOC) diff --git a/common/version.c b/common/version.c index aae63fdb8..c32fa3cd1 100644 --- a/common/version.c +++ b/common/version.c @@ -100,4 +100,11 @@ awesome_release_string(void) return AWESOME_RELEASE; } + +int +awesome_default_api_level(void) +{ + return AWESOME_API_LEVEL; +} + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/common/version.h b/common/version.h index 7bf3bc908..776df5580 100644 --- a/common/version.h +++ b/common/version.h @@ -25,6 +25,7 @@ void eprint_version(void) __attribute__ ((noreturn)); const char *awesome_version_string(void); const char *awesome_release_string(void); +int awesome_default_api_level(void); #endif diff --git a/globalconf.h b/globalconf.h index cf55493b1..990700d05 100644 --- a/globalconf.h +++ b/globalconf.h @@ -224,6 +224,8 @@ typedef struct xcb_generic_event_t *pending_event; /** The exit code that main() will return with */ int exit_code; + /** The Global API level */ + int api_level; } awesome_t; extern awesome_t globalconf; diff --git a/luaa.c b/luaa.c index 3e9455f74..a5cb333ad 100644 --- a/luaa.c +++ b/luaa.c @@ -540,15 +540,42 @@ static int luaA_get_active_modifiers(lua_State *L) } /** - * The version of awesome. + * The AwesomeWM version. * @tfield string version */ /** - * The release name of awesome. + * The AwesomeWM release name. * @tfield string release */ +/** + * The AwesomeWM API level. + * + * By default, this matches the major version (first component of the version). + * + * API levels are used to allow newer version of AwesomeWM to alter the behavior + * and subset deprecated APIs. Using an older API level than the current major + * version allows to use legacy `rc.lua` with little porting. However, they wont + * be able to use all the new features. Attempting to use a newer feature along + * with an older API level is not and will not be supported, even if it almost + * works. Keeping up to date with the newer API levels is highly recommended. + * + * Going the other direction, setting an higher API level allows to take + * advantage of experimental feature. It will also be much harsher when it comes + * to deprecation. Setting the API level value beyond `current+3` will treat + * using APIs currently pending deprecation as fatal errors. All new code + * submitted to the upstream AwesomeWM codebase is forbidden to use deprecated + * APIs. Testing your patches with mode and the default config is recommended + * before submitting a patch. + * + * You can use the `-l` command line option or `api-level` modeline key to set + * the API level for your `rc.lua`. This setting is global and read only, + * individual modules cannot set their own API level. + * + * @tfield string api_level + */ + /** * The configuration file which has been loaded. * @tfield string conffile @@ -616,6 +643,12 @@ luaA_awesome_index(lua_State *L) return 1; } + if(A_STREQ(buf, "api_level")) + { + lua_pushinteger(L, globalconf.api_level); + return 1; + } + if(A_STREQ(buf, "startup")) { lua_pushboolean(L, globalconf.loop == NULL); diff --git a/options.c b/options.c index 380c7b523..dc9b760da 100644 --- a/options.c +++ b/options.c @@ -24,12 +24,41 @@ #include #include +#include #include #include #define KEY_VALUE_BUF_MAX 64 #define READ_BUF_MAX 127 +static void +set_api_level(char *value) +{ + if (!value) + return; + + char *ptr; + int ret = strtol(value, &ptr, 10); + + /* There is no valid number at all */ + if (value == ptr) { + fprintf(stderr, "Invalid API level %s\n", value); + return; + } + + /* There is a number, but also letters, this is invalid */ + if (ptr[0] != '\0' && ptr[0] != '.') { + fprintf(stderr, "Invalid API level %s\n", value); + return; + } + + /* This API level doesn't exist, fallback to v4 */ + if (ret < 4) + ret = 4; + + globalconf.api_level = ret; +} + static void push_arg(string_array_t *args, char *value, size_t *len) { @@ -327,15 +356,16 @@ exit_help(int exit_code) FILE *outfile = (exit_code == EXIT_SUCCESS) ? stdout : stderr; fprintf(outfile, "Usage: awesome [OPTION]\n\ - -h, --help show help\n\ - -v, --version show version\n\ - -f, --force ignore modelines and apply the command line arguments\n\ - -c, --config FILE configuration file to use\n\ - --search DIR add a directory to the library search path\n\ - -k, --check check configuration file syntax\n\ - -a, --no-argb disable client transparency support\n\ - -m, --screen on|off enable or disable automatic screen creation (default: on)\n\ - -r, --replace replace an existing window manager\n"); + -h, --help show help\n\ + -v, --version show version\n\ + -c, --config FILE configuration file to use\n\ + -f, --force ignore modelines and apply the command line arguments\n\ + --search DIR add a directory to the library search path\n\ + -k, --check check configuration file syntax\n\ + -a, --no-argb disable client transparency support\n\ + -l --api-level LEVEL select a different API support level than the current version \n\ + -m, --screen on|off enable or disable automatic screen creation (default: on)\n\ + -r, --replace replace an existing window manager\n"); exit(exit_code); } @@ -348,23 +378,24 @@ options_check_args(int argc, char **argv, int *init_flags, string_array_t *paths static struct option long_options[] = { - { "help", NO_ARG, NULL, 'h' }, - { "version", NO_ARG, NULL, 'v' }, - { "config", ARG , NULL, 'c' }, - { "force" , NO_ARG, NULL, 'f' }, - { "check", NO_ARG, NULL, 'k' }, - { "search", ARG , NULL, 's' }, - { "no-argb", NO_ARG, NULL, 'a' }, - { "replace", NO_ARG, NULL, 'r' }, - { "screen" , ARG , NULL, 'm' }, - { "reap", ARG , NULL, '\1' }, - { NULL, NO_ARG, NULL, 0 } + { "help" , NO_ARG, NULL, 'h' }, + { "version" , NO_ARG, NULL, 'v' }, + { "config" , ARG , NULL, 'c' }, + { "force" , NO_ARG, NULL, 'f' }, + { "check" , NO_ARG, NULL, 'k' }, + { "search" , ARG , NULL, 's' }, + { "no-argb" , NO_ARG, NULL, 'a' }, + { "replace" , NO_ARG, NULL, 'r' }, + { "screen" , ARG , NULL, 'm' }, + { "api-level" , ARG , NULL, 'l' }, + { "reap" , ARG , NULL, '\1' }, + { NULL , NO_ARG, NULL, 0 } }; char *confpath = NULL; int opt; - while((opt = getopt_long(argc, argv, "vhkc:arm:", + while((opt = getopt_long(argc, argv, "vhkc:arml:", long_options, NULL)) != -1) { switch(opt) { @@ -405,6 +436,9 @@ options_check_args(int argc, char **argv, int *init_flags, string_array_t *paths case 'r': (*init_flags) |= INIT_FLAG_REPLACE_WM; break; + case 'l': + set_api_level(optarg); + break; case '\1': /* Silently ignore --reap and its argument */ break; diff --git a/tests/examples/shims/awesome.lua b/tests/examples/shims/awesome.lua index ac4035725..64b0da43b 100644 --- a/tests/examples/shims/awesome.lua +++ b/tests/examples/shims/awesome.lua @@ -83,7 +83,8 @@ function awesome.xrdb_get_value() end -- Always show deprecated messages -awesome.version = "v9999" +awesome.version = "v9999" +awesome.api_level = 9999 -- SVG are composited. Without it we need a root surface awesome.composite_manager_running = true