From 03fbd2f3b462ef3c503f47e5928771780effa801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Andr=C3=A9=20Charles=20Gantner?= Date: Sun, 2 Jun 2024 16:11:34 +0200 Subject: [PATCH 1/8] wip --- src/store.c | 142 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 55 deletions(-) diff --git a/src/store.c b/src/store.c index 6dab784..bfe61e8 100644 --- a/src/store.c +++ b/src/store.c @@ -1,65 +1,95 @@ #include "wdisplays.h" #include +#include #include +#include #include #include #include #include -#include -#include + #define MAX_NAME_LENGTH 256 #define MAX_MONITORS_NUM 10 + struct wd_head_config; struct profile_line { int start; int end; }; + char *get_config_file_path() { - char defaultPath[PATH_MAX]; // platform based marco PATH_MAX - char wdisplaysPath[PATH_MAX]; - // if $XDG_CONFIG_HOME is set, use it - { - const char *configDir = getenv("XDG_CONFIG_HOME"); - char defaultConfigDir[PATH_MAX]; + char kanshiConfigPath[PATH_MAX]; + char wdisplaysPath[PATH_MAX]; + char defaultConfigDir[PATH_MAX]; + // if $XDG_CONFIG_HOME is set, use it + { + char *configDir = getenv("XDG_CONFIG_HOME"); + if (configDir == NULL) { // fallback to $HOME + configDir = getenv("HOME"); if (configDir == NULL) { - const char *homeDir = getenv("HOME"); - if (homeDir == NULL) { - perror("Cannot find home directory"); - return NULL; - } - snprintf(defaultConfigDir, sizeof(defaultConfigDir), "%s/.config", homeDir); + perror("Cannot find home directory"); + return NULL; } else { - snprintf(defaultConfigDir, sizeof(defaultConfigDir), "%s", configDir); + // configdir is $HOME/config + snprintf(defaultConfigDir, sizeof(defaultConfigDir), "%s/.config", + configDir); } - snprintf(defaultPath, sizeof(defaultPath), "%s/kanshi/config", defaultConfigDir); - snprintf(wdisplaysPath, sizeof(wdisplaysPath), "%s/wdisplays/config", defaultConfigDir); + } else { + // configDir is $XDG_CONFIG_HOME + snprintf(defaultConfigDir, sizeof(defaultConfigDir), "%s", configDir); } + } + // set default kanshi config path + snprintf(kanshiConfigPath, sizeof(kanshiConfigPath), "%s/kanshi/config", + defaultConfigDir); - FILE *wdisplaysFile = fopen(wdisplaysPath, "r"); - if (wdisplaysFile != NULL) { - char line[LINE_MAX]; // LINE_MAX is a platform based marco - - // try to match "store_path" term - while (fgets(line, sizeof(line), wdisplaysFile) != NULL) { - if (strstr(line, "store_path") != NULL) { - // if found, extract path - char *pathStart = strchr(line, '='); - if (pathStart != NULL) { - pathStart++; // skip '=' - char *pathEnd = strchr(pathStart, '\n'); - if (pathEnd != NULL) { - *pathEnd = '\0'; // replace '\n' with '\0' - fclose(wdisplaysFile); - return strdup(pathStart); // return path - } - } - } - } - fclose(wdisplaysFile); - } + // look for store_path in wdisplays.conf + snprintf(wdisplaysPath, sizeof(wdisplaysPath), "%s/wdisplays.conf", + defaultConfigDir); + + FILE *wdisplaysFile = fopen(wdisplaysPath, "r"); + if (wdisplaysFile != NULL) { + char line[LINE_MAX]; // LINE_MAX is a platform-dependendant macro + + // try to match "store_path" term + while (fgets(line, sizeof(line), wdisplaysFile) != NULL) { + if (strstr(line, "store_path") != NULL) { + // if found, extract path + char *pathStart = strchr(line, '='); + if (pathStart != NULL) { + pathStart++; // skip '=' + while (*pathStart == ' ') + pathStart++; // skip spaces between '=' and the start of the path + char *pathEnd = strchr( + pathStart, '\n'); // this fails if store_path is the last line and + // the file doesn't end with a newline + size_t pathLen; + if (pathEnd != NULL) { + pathLen = pathEnd - pathStart; + } else { // store_path= is the last line and there's no newline at the + // end of the file + pathLen = strnlen(pathStart, PATH_MAX); // read up to PATH_MAX chars + } + // save path + strncpy(kanshiConfigPath, pathStart, pathLen); + } else + ; // store_path was not followed by an equal sign on this line + } else + ; // this line does not contain store_path + } // reached end of file + fclose(wdisplaysFile); + } else + ; // can't open config file, continue - // if store_path is not found in wdisplays config file, return default path - return strdup(defaultPath); + // look for WDISPLAYS_KANSHI_CONFIG + { + char *envKanshiConf = getenv("WDISPLAYS_KANSHI_CONFIG"); + if (envKanshiConf != NULL) + strncpy(kanshiConfigPath, envKanshiConf, sizeof(kanshiConfigPath)); + else + ; + } + return strndup(kanshiConfigPath, PATH_MAX); } struct profile_line match(char **descriptions, int num, char *filename) { @@ -108,7 +138,8 @@ struct profile_line match(char **descriptions, int num, char *filename) { while (isspace(*trimmedBuffer)) { trimmedBuffer++; // skip leading spaces } - sscanf(trimmedBuffer, "output \"%99[^\"]\"", outputName); // extract output name + sscanf(trimmedBuffer, "output \"%99[^\"]\"", + outputName); // extract output name // check if the output name is in the descriptions bool matched = false; @@ -148,7 +179,7 @@ struct profile_line match(char **descriptions, int num, char *filename) { int store_config(struct wl_list *outputs) { char *file_name = get_config_file_path(); char tmp_file_name[PATH_MAX]; - sprintf(tmp_file_name,"%s.tmp",file_name); + sprintf(tmp_file_name, "%s.tmp", file_name); char *descriptions[MAX_MONITORS_NUM]; for (int i = 0; i < MAX_MONITORS_NUM; i++) { @@ -197,11 +228,12 @@ int store_config(struct wl_list *outputs) { if (description_index < MAX_MONITORS_NUM) { descriptions[description_index] = strdup(head->description); // write output config in given format - sprintf( - outputConfigs[description_index], - "output \"%s\" position %d,%d mode %dx%d@%.4f scale %.2f transform %s", - head->description, output->x, output->y, output->width, - output->height, output->refresh / 1.0e3, output->scale, trans_str); + sprintf(outputConfigs[description_index], + "output \"%s\" position %d,%d mode %dx%d@%.4f scale %.2f " + "transform %s", + head->description, output->x, output->y, output->width, + output->height, output->refresh / 1.0e3, output->scale, + trans_str); description_index++; } else { free(trans_str); @@ -226,7 +258,7 @@ int store_config(struct wl_list *outputs) { return 1; } fprintf(file, "\nprofile {\n"); - for (int i = 0; i= matched_profile.start && _line < matched_profile.end - 1) { - if(_i_output>=num_of_monitors){ + if (_i_output >= num_of_monitors) { perror("Null pointer"); fclose(tmp); fclose(file); return 1; } - fprintf(tmp," %s\n",outputConfigs[_i_output]); + fprintf(tmp, " %s\n", outputConfigs[_i_output]); free(outputConfigs[_i_output]); _i_output++; - } else{ - fprintf(tmp,"%s",_buffer); + } else { + fprintf(tmp, "%s", _buffer); } _line++; } fclose(file); fclose(tmp); - + remove(file_name); rename(tmp_file_name, file_name); free(file_name); } return 0; -} \ No newline at end of file +} From 1c0d34a457ad340f387aeeb8ab362508c519edf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Andr=C3=A9=20Charles=20Gantner?= Date: Sun, 2 Jun 2024 16:13:55 +0200 Subject: [PATCH 2/8] Fix deprecated flag --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index e9690c4..a81e348 100644 --- a/src/main.c +++ b/src/main.c @@ -1083,7 +1083,7 @@ static void activate(GtkApplication* app, gpointer user_data) { int main(int argc, char *argv[]) { g_setenv("GDK_GL", "gles", FALSE); - GtkApplication *app = gtk_application_new(WDISPLAYS_APP_ID, G_APPLICATION_FLAGS_NONE); + GtkApplication *app = gtk_application_new(WDISPLAYS_APP_ID, G_APPLICATION_DEFAULT_FLAGS); g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); int status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); From f478e76ba65a9329e7239d1d4727a481c68632c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Andr=C3=A9=20Charles=20Gantner?= Date: Sun, 2 Jun 2024 20:01:44 +0200 Subject: [PATCH 3/8] check config path only on startup --- src/store.c | 158 ++++++++++++++++++++++++++---------------------- src/wdisplays.h | 31 ++++++++-- 2 files changed, 111 insertions(+), 78 deletions(-) diff --git a/src/store.c b/src/store.c index bfe61e8..fc970c4 100644 --- a/src/store.c +++ b/src/store.c @@ -17,7 +17,9 @@ struct profile_line { int end; }; -char *get_config_file_path() { +typedef enum { Looking_for_profile, Looking_for_outputs, Found } parser_states; + +char *wd_get_config_file_path() { char kanshiConfigPath[PATH_MAX]; char wdisplaysPath[PATH_MAX]; char defaultConfigDir[PATH_MAX]; @@ -27,7 +29,9 @@ char *get_config_file_path() { if (configDir == NULL) { // fallback to $HOME configDir = getenv("HOME"); if (configDir == NULL) { - perror("Cannot find home directory"); + dprintf( + 2, "%s:%i:%s(): Cannot find $XDG_CONFIG_HOME nor $HOME directories", + __FILE__, __LINE__, __func__); return NULL; } else { // configdir is $HOME/config @@ -58,7 +62,7 @@ char *get_config_file_path() { char *pathStart = strchr(line, '='); if (pathStart != NULL) { pathStart++; // skip '=' - while (*pathStart == ' ') + while (isspace(*pathStart)) pathStart++; // skip spaces between '=' and the start of the path char *pathEnd = strchr( pathStart, '\n'); // this fails if store_path is the last line and @@ -78,8 +82,12 @@ char *get_config_file_path() { ; // this line does not contain store_path } // reached end of file fclose(wdisplaysFile); - } else - ; // can't open config file, continue + } else { + // can't open config file + dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, + wdisplaysPath); + perror(NULL); + } // look for WDISPLAYS_KANSHI_CONFIG { @@ -89,95 +97,100 @@ char *get_config_file_path() { else ; } - return strndup(kanshiConfigPath, PATH_MAX); + char *finalPath = strndup(kanshiConfigPath, PATH_MAX); + if (finalPath == NULL) { + dprintf(2, "%s:%i:%s(): ", __FILE__, __LINE__, __func__); + perror("Failed to allocate memory for kanshi config path"); + } + return finalPath; } -struct profile_line match(char **descriptions, int num, char *filename) { +struct profile_line match(char **descriptions, int num, const char *filename) { struct profile_line matched_profile; matched_profile.start = -1; matched_profile.end = -1; // -1 means not found FILE *configFile = fopen(filename, "r"); if (configFile == NULL) { - perror("File open failed."); + dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, + filename); + perror(NULL); return matched_profile; } // buffer to store each line char buffer[LINE_MAX]; - char profileName[MAX_NAME_LENGTH]; + char *profileName; int profileStartLine = 0; // mark the start line of matched profile int profileEndLine = 0; // mark the end line of matched profile - int lineCount = 0; // current line number - - while (fgets(buffer, sizeof(buffer), configFile) != NULL) { + int lineCount = 0; // current line number + uint32_t profileMatchedNum = 0; // current number of matched outputs + parser_states ps = Looking_for_profile; // current state of the parser + while (ps != Found && fgets(buffer, sizeof(buffer), configFile) != NULL) { lineCount++; - - // check if "profile" keyword is in the line - if (strstr(buffer, "profile") != NULL) { - // extract profile name - sscanf(buffer, "profile %s {", profileName); - - // the number of matched outputs - uint32_t profileMatchedNum = 0; - - // record the start line of the profile - profileStartLine = lineCount; - - while (fgets(buffer, sizeof(buffer), configFile) != NULL) { - lineCount++; - - // check if the profile ends - if (buffer[0] == '}') { - profileEndLine = lineCount; - break; - } - char outputName[MAX_NAME_LENGTH]; - // 从当前行提取输出名称 - char *trimmedBuffer = buffer; - while (isspace(*trimmedBuffer)) { - trimmedBuffer++; // skip leading spaces + switch (ps) { + case Found: + break; // unreachable code + + case Looking_for_profile:; + // check if "profile" keyword is in the line and remember its position + char *pstart = strstr(buffer, "profile "); + if (pstart != NULL) { + pstart +=7; + char *pend = strchr(pstart, '{'); // find the end of the profile name + while (isspace(*pend)){ + pend--; } - sscanf(trimmedBuffer, "output \"%99[^\"]\"", - outputName); // extract output name + size_t pnsize = pend - pstart; + // use strndup to extract it without being size constrained + profileName = strndup(pstart, pnsize); + // record the start line of the profile + profileStartLine = lineCount; + ps = Looking_for_outputs; + } + break; + case Looking_for_outputs: + // check if the profile ends + if (buffer[0] == '}') { + profileEndLine = lineCount; + if (profileMatchedNum == num) + ps = Found; + } else { + char *on_start = strstr(buffer, "output"); + on_start = strchr(on_start, '"'); + on_start++; + char *on_end = strchr(on_start, '"'); + char *outputName = strndup(on_start, on_end - on_start); // check if the output name is in the descriptions - bool matched = false; - for (int i = 0; descriptions[i] != NULL; i++) { - if (strcmp(outputName, descriptions[i]) == 0) { - matched = true; - profileMatchedNum++; - break; - } - } - - if (!matched) { + int i = 0; + while (descriptions[i] != NULL && strcmp(outputName, descriptions[i])) + i++; + if (descriptions[i] != NULL) { + profileMatchedNum++; + } else { // if any output is not matched, break profileMatchedNum = 0; - break; + ps = Looking_for_profile; } } - - if (profileMatchedNum == num) { - printf("Matched profile:%s\n", profileName); - printf("Start line:%d\n", profileStartLine); - matched_profile.start = profileStartLine; - printf("End line:%d\n", profileEndLine); - matched_profile.end = profileEndLine; - - fclose(configFile); - return matched_profile; - } + break; } } - fclose(configFile); - printf("Cannot find existing profile to match\n"); + if (ps == Found) { + printf("Matched profile:%s\n", profileName); + printf("Start line:%d\nEnd line:%d\n", profileStartLine, profileEndLine); + matched_profile.start = profileStartLine; + matched_profile.end = profileEndLine; + } else + dprintf(2, "%s:%i:%s(): Cannot find existing profile to match\n", __FILE__, + __LINE__, __func__); return matched_profile; } -int store_config(struct wl_list *outputs) { - char *file_name = get_config_file_path(); +int wd_store_config(struct wl_list *outputs) { + const char *file_name = wd_get_kanshi_config(); char tmp_file_name[PATH_MAX]; sprintf(tmp_file_name, "%s.tmp", file_name); @@ -237,7 +250,8 @@ int store_config(struct wl_list *outputs) { description_index++; } else { free(trans_str); - printf("Too many monitor! 10 is the"); + dprintf(2, "Too many monitor!\n\t%i is the maximum allowed number", + MAX_MONITORS_NUM); return 1; } @@ -253,8 +267,9 @@ int store_config(struct wl_list *outputs) { // append new profile FILE *file = fopen(file_name, "a"); if (file == NULL) { - perror("File open failed."); - free(file_name); + dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, + file_name); + perror(NULL); return 1; } fprintf(file, "\nprofile {\n"); @@ -269,14 +284,14 @@ int store_config(struct wl_list *outputs) { FILE *file = fopen(file_name, "r"); if (file == NULL) { perror("File open failed."); - free(file_name); return 1; } FILE *tmp = fopen(tmp_file_name, "w"); if (tmp == NULL) { - perror("Tmp file cannot be created."); + dprintf(2, "%s:%i:%s(): Can't create %s : ", __FILE__, __LINE__, __func__, + tmp_file_name); + perror(NULL); fclose(file); - free(file_name); return 1; } char _buffer[LINE_MAX]; @@ -304,7 +319,6 @@ int store_config(struct wl_list *outputs) { remove(file_name); rename(tmp_file_name, file_name); - free(file_name); } return 0; diff --git a/src/wdisplays.h b/src/wdisplays.h index 4824017..d3da26e 100644 --- a/src/wdisplays.h +++ b/src/wdisplays.h @@ -224,7 +224,6 @@ struct wd_state { struct wd_render_data render; }; - /* * Creates the application state structure. */ @@ -243,12 +242,14 @@ void wd_fatal_error(int status, const char *message); /* * Add an output to the list of screen captured outputs. */ -void wd_add_output(struct wd_state *state, struct wl_output *wl_output, struct wl_display *display); +void wd_add_output(struct wd_state *state, struct wl_output *wl_output, + struct wl_display *display); /* * Remove an output from the list of screen captured outputs. */ -void wd_remove_output(struct wd_state *state, struct wl_output *wl_output, struct wl_display *display); +void wd_remove_output(struct wd_state *state, struct wl_output *wl_output, + struct wl_display *display); /* * Finds the output associated with a given head. Can return NULL if the head's @@ -263,12 +264,14 @@ struct wd_head *wd_find_head(struct wd_state *state, struct wd_output *output); /* * Starts listening for output management events from the compositor. */ -void wd_add_output_management_listener(struct wd_state *state, struct wl_display *display); +void wd_add_output_management_listener(struct wd_state *state, + struct wl_display *display); /* * Sends updated display configuration back to the compositor. */ -void wd_apply_state(struct wd_state *state, struct wl_list *new_outputs, struct wl_display *display); +void wd_apply_state(struct wd_state *state, struct wl_list *new_outputs, + struct wl_display *display); /* * Queues capture of the next frame of all screens. @@ -316,7 +319,8 @@ struct wd_gl_data *wd_gl_setup(void); /* * Renders the GL scene. */ -void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info, uint64_t tick); +void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info, + uint64_t tick); /* * Destroys the GL shaders. @@ -339,4 +343,19 @@ void wd_redraw_overlay(struct wd_output *output); */ void wd_destroy_overlay(struct wd_output *output); +/* + * Locate kanshi config + */ +char *wd_get_config_file_path(); + +/* + * Returns kanshi config path + */ +char *wd_get_kanshi_config(); + +/* + * Updates kanshi config + */ +int wd_store_config(struct wl_list *outputs); + #endif From 709f80e7bb035e4a63f3864269ad3fb686268f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Andr=C3=A9=20Charles=20Gantner?= Date: Sun, 2 Jun 2024 20:36:20 +0200 Subject: [PATCH 4/8] use HEADS_MAX from wdisplays.h --- src/store.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/store.c b/src/store.c index fc970c4..468cc44 100644 --- a/src/store.c +++ b/src/store.c @@ -9,7 +9,6 @@ #include #define MAX_NAME_LENGTH 256 -#define MAX_MONITORS_NUM 10 struct wd_head_config; struct profile_line { @@ -194,13 +193,13 @@ int wd_store_config(struct wl_list *outputs) { char tmp_file_name[PATH_MAX]; sprintf(tmp_file_name, "%s.tmp", file_name); - char *descriptions[MAX_MONITORS_NUM]; - for (int i = 0; i < MAX_MONITORS_NUM; i++) { + char *descriptions[HEADS_MAX]; + for (int i = 0; i < HEADS_MAX; i++) { descriptions[i] = NULL; } - char *outputConfigs[MAX_MONITORS_NUM]; - for (int i = 0; i < MAX_MONITORS_NUM; i++) { + char *outputConfigs[HEADS_MAX]; + for (int i = 0; i < HEADS_MAX; i++) { outputConfigs[i] = (char *)malloc(MAX_NAME_LENGTH); } @@ -238,7 +237,7 @@ int wd_store_config(struct wl_list *outputs) { break; } - if (description_index < MAX_MONITORS_NUM) { + if (description_index < HEADS_MAX) { descriptions[description_index] = strdup(head->description); // write output config in given format sprintf(outputConfigs[description_index], @@ -251,7 +250,7 @@ int wd_store_config(struct wl_list *outputs) { } else { free(trans_str); dprintf(2, "Too many monitor!\n\t%i is the maximum allowed number", - MAX_MONITORS_NUM); + HEADS_MAX); return 1; } From 3a062cd525cc95cace3b96c681280b882707b95e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Andr=C3=A9=20Charles=20Gantner?= Date: Sun, 2 Jun 2024 20:43:45 +0200 Subject: [PATCH 5/8] remove useless strcpy --- src/store.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/store.c b/src/store.c index 468cc44..fd6c999 100644 --- a/src/store.c +++ b/src/store.c @@ -209,31 +209,31 @@ int wd_store_config(struct wl_list *outputs) { struct wd_head *head = output->head; // for transform - char *trans_str = (char *)malloc(15 * sizeof(char)); + char* trans_str; switch (output->transform) { case WL_OUTPUT_TRANSFORM_NORMAL: - strcpy(trans_str, "normal"); + trans_str = "normal"; break; case WL_OUTPUT_TRANSFORM_90: - strcpy(trans_str, "90"); + trans_str = "90"; break; case WL_OUTPUT_TRANSFORM_180: - strcpy(trans_str, "180"); + trans_str = "180"; break; case WL_OUTPUT_TRANSFORM_270: - strcpy(trans_str, "270"); + trans_str = "270"; break; case WL_OUTPUT_TRANSFORM_FLIPPED_90: - strcpy(trans_str, "flipped-90"); + trans_str = "flipped-90"; break; case WL_OUTPUT_TRANSFORM_FLIPPED_180: - strcpy(trans_str, "flipped-180"); + trans_str = "flipped-180"; break; case WL_OUTPUT_TRANSFORM_FLIPPED_270: - strcpy(trans_str, "flipped-270"); + trans_str = "flipped-270"; break; default: - strcpy(trans_str, "normal"); + trans_str = "normal"; break; } @@ -248,13 +248,10 @@ int wd_store_config(struct wl_list *outputs) { trans_str); description_index++; } else { - free(trans_str); dprintf(2, "Too many monitor!\n\t%i is the maximum allowed number", HEADS_MAX); return 1; } - - free(trans_str); } int num_of_monitors = description_index; From 80f1c6ee14f71d397b8701d43bfd7d4c0ba1d20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Andr=C3=A9=20Charles=20Gantner?= Date: Sat, 7 Sep 2024 11:22:18 +0200 Subject: [PATCH 6/8] update readme and meson syntax --- CHANGELOG.md | 8 ++++++++ protocol/meson.build | 2 +- src/meson.build | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3803a77..86d5c59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ This project tries to adhere to [Semantic Versioning][2]. ## [Unreleased] +### Added + +Support for saving kanshi config file + +### Changed + +### Fixed + ## [1.1.1] - 2023-07-01 ### Added diff --git a/protocol/meson.build b/protocol/meson.build index 5f34a7a..670a4af 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -5,7 +5,7 @@ wayland_scanner = find_program('wayland-scanner') wayland_client = dependency('wayland-client') wayland_protos = dependency('wayland-protocols', version: '>=1.17') -wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') +wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') wayland_scanner_code = generator( wayland_scanner, diff --git a/src/meson.build b/src/meson.build index 8527452..286f631 100644 --- a/src/meson.build +++ b/src/meson.build @@ -6,7 +6,7 @@ m_dep = cc.find_library('m', required : false) rt_dep = cc.find_library('rt', required : false) gdk = dependency('gdk-3.0', version: '>= 3.24') gtk = dependency('gtk+-3.0', version: '>= 3.24') -assert(gdk.get_pkgconfig_variable('targets').split().contains('wayland'), 'Wayland GDK backend not present') +assert(gdk.get_variable('targets').split().contains('wayland'), 'Wayland GDK backend not present') epoxy = dependency('epoxy') configure_file(input: 'config.h.in', output: 'config.h', configuration: conf) From 4b9da490e4ccacd6d5bed70266841173b2e0989b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Andr=C3=A9=20Charles=20Gantner?= Date: Sun, 2 Jun 2024 22:57:40 +0200 Subject: [PATCH 7/8] clang-format --- .clang-format | 57 ++++++++++++- src/store.c | 212 +++++++++++++++++++----------------------------- src/wdisplays.h | 19 ++--- 3 files changed, 144 insertions(+), 144 deletions(-) diff --git a/.clang-format b/.clang-format index 912692d..a981890 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,55 @@ --- -IndentWidth: '2' - -... +Language: Cpp +IndentWidth: 2 +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true + AlignCompound: true + PadOperators: true +AlignConsecutiveBitFields: Consecutive +AlignConsecutiveMacros: Consecutive +AlignConsecutiveShortCaseStatements: + Enabled: true + # AlignCaseArrows: true + AlignCaseColons: true +AlignOperands: Align +AlignTrailingComments: Always +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: true +# AllowShortCaseExpressionOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: AllIfsAndElse +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +BinPackArguments: true +BinPackParameters: true +BreakBeforeBraces: Attach +BreakBeforeConceptDeclarations: Never +BreakBeforeBinaryOperators: true +BreakBeforeTernaryOperators: true +ColumnLimit: 128 +IndentCaseBlocks: false +IndentCaseLabels: true +IndentPPDirectives: AfterHash +InsertBraces: false +InsertNewlineAtEOF: true +LineEnding: LF +PointerAlignment: Right +QualifierAlignment: Left +ReferenceAlignment: Right +ReflowComments: true +RemoveBracesLLVM: true +SeparateDefinitionBlocks: Always +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeParens: ControlStatementsExceptControlMacros +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesInAngles: Never +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: 1 +SpacesInParens: Never +UseTab: Never diff --git a/src/store.c b/src/store.c index fd6c999..f2c43c2 100644 --- a/src/store.c +++ b/src/store.c @@ -11,6 +11,7 @@ #define MAX_NAME_LENGTH 256 struct wd_head_config; + struct profile_line { int start; int end; @@ -28,27 +29,21 @@ char *wd_get_config_file_path() { if (configDir == NULL) { // fallback to $HOME configDir = getenv("HOME"); if (configDir == NULL) { - dprintf( - 2, "%s:%i:%s(): Cannot find $XDG_CONFIG_HOME nor $HOME directories", - __FILE__, __LINE__, __func__); + dprintf(2, "%s:%i:%s(): Cannot find $XDG_CONFIG_HOME nor $HOME directories", __FILE__, __LINE__, __func__); return NULL; - } else { - // configdir is $HOME/config - snprintf(defaultConfigDir, sizeof(defaultConfigDir), "%s/.config", - configDir); + } else { // configdir is $HOME/config + snprintf(defaultConfigDir, sizeof(defaultConfigDir), "%s/.config", configDir); } - } else { - // configDir is $XDG_CONFIG_HOME + } else { // configDir is $XDG_CONFIG_HOME snprintf(defaultConfigDir, sizeof(defaultConfigDir), "%s", configDir); } } + // set default kanshi config path - snprintf(kanshiConfigPath, sizeof(kanshiConfigPath), "%s/kanshi/config", - defaultConfigDir); + snprintf(kanshiConfigPath, sizeof(kanshiConfigPath), "%s/kanshi/config", defaultConfigDir); // look for store_path in wdisplays.conf - snprintf(wdisplaysPath, sizeof(wdisplaysPath), "%s/wdisplays.conf", - defaultConfigDir); + snprintf(wdisplaysPath, sizeof(wdisplaysPath), "%s/wdisplays.conf", defaultConfigDir); FILE *wdisplaysFile = fopen(wdisplaysPath, "r"); if (wdisplaysFile != NULL) { @@ -60,39 +55,30 @@ char *wd_get_config_file_path() { // if found, extract path char *pathStart = strchr(line, '='); if (pathStart != NULL) { - pathStart++; // skip '=' - while (isspace(*pathStart)) - pathStart++; // skip spaces between '=' and the start of the path - char *pathEnd = strchr( - pathStart, '\n'); // this fails if store_path is the last line and - // the file doesn't end with a newline + pathStart++; // skip '=' + while (isspace(*pathStart)) pathStart++; // skip spaces between '=' and the start of the path + char *pathEnd = strchr(pathStart, '\n'); size_t pathLen; - if (pathEnd != NULL) { - pathLen = pathEnd - pathStart; - } else { // store_path= is the last line and there's no newline at the - // end of the file - pathLen = strnlen(pathStart, PATH_MAX); // read up to PATH_MAX chars - } + if (pathEnd != NULL) pathLen = pathEnd - pathStart; + else // store_path= is the last line and there's no newline at the end of the file + pathLen = strnlen(pathStart, PATH_MAX); // save path strncpy(kanshiConfigPath, pathStart, pathLen); } else - ; // store_path was not followed by an equal sign on this line + ; // store_path was not followed by an equal sign on this line } else ; // this line does not contain store_path } // reached end of file fclose(wdisplaysFile); - } else { - // can't open config file - dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, - wdisplaysPath); + } else { // can't open config file + dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, wdisplaysPath); perror(NULL); } // look for WDISPLAYS_KANSHI_CONFIG { char *envKanshiConf = getenv("WDISPLAYS_KANSHI_CONFIG"); - if (envKanshiConf != NULL) - strncpy(kanshiConfigPath, envKanshiConf, sizeof(kanshiConfigPath)); + if (envKanshiConf != NULL) strncpy(kanshiConfigPath, envKanshiConf, sizeof(kanshiConfigPath)); else ; } @@ -107,12 +93,11 @@ char *wd_get_config_file_path() { struct profile_line match(char **descriptions, int num, const char *filename) { struct profile_line matched_profile; matched_profile.start = -1; - matched_profile.end = -1; + matched_profile.end = -1; // -1 means not found - FILE *configFile = fopen(filename, "r"); + FILE *configFile = fopen(filename, "r"); if (configFile == NULL) { - dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, - filename); + dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, filename); perror(NULL); return matched_profile; } @@ -120,60 +105,55 @@ struct profile_line match(char **descriptions, int num, const char *filename) { char buffer[LINE_MAX]; char *profileName; int profileStartLine = 0; // mark the start line of matched profile - int profileEndLine = 0; // mark the end line of matched profile + int profileEndLine = 0; // mark the end line of matched profile - int lineCount = 0; // current line number - uint32_t profileMatchedNum = 0; // current number of matched outputs - parser_states ps = Looking_for_profile; // current state of the parser + int lineCount = 0; // current line number + uint32_t profileMatchedNum = 0; // current number of matched outputs + parser_states ps = Looking_for_profile; // current state of the parser while (ps != Found && fgets(buffer, sizeof(buffer), configFile) != NULL) { lineCount++; switch (ps) { - case Found: - break; // unreachable code + case Found: break; // unreachable code - case Looking_for_profile:; - // check if "profile" keyword is in the line and remember its position - char *pstart = strstr(buffer, "profile "); - if (pstart != NULL) { - pstart +=7; - char *pend = strchr(pstart, '{'); // find the end of the profile name - while (isspace(*pend)){ - pend--; + case Looking_for_profile:; + // check if "profile" keyword is in the line and remember its position + char *pstart = strstr(buffer, "profile "); + if (pstart != NULL) { + pstart += 7; + char *pend = strchr(pstart, '{'); // find the end of the profile name + while (isspace(*pend)) pend--; + size_t pnsize = pend - pstart; + // use strndup to extract it without being size constrained + profileName = strndup(pstart, pnsize); + // record the start line of the profile + profileStartLine = lineCount; + ps = Looking_for_outputs; } - size_t pnsize = pend - pstart; - // use strndup to extract it without being size constrained - profileName = strndup(pstart, pnsize); - // record the start line of the profile - profileStartLine = lineCount; - ps = Looking_for_outputs; - } - break; + break; - case Looking_for_outputs: - // check if the profile ends - if (buffer[0] == '}') { - profileEndLine = lineCount; - if (profileMatchedNum == num) - ps = Found; - } else { - char *on_start = strstr(buffer, "output"); - on_start = strchr(on_start, '"'); - on_start++; - char *on_end = strchr(on_start, '"'); - char *outputName = strndup(on_start, on_end - on_start); - // check if the output name is in the descriptions - int i = 0; - while (descriptions[i] != NULL && strcmp(outputName, descriptions[i])) - i++; - if (descriptions[i] != NULL) { - profileMatchedNum++; + case Looking_for_outputs: + // check if the profile ends + if (buffer[0] == '}') { + profileEndLine = lineCount; + if (profileMatchedNum == num) ps = Found; } else { - // if any output is not matched, break - profileMatchedNum = 0; - ps = Looking_for_profile; + char *on_start = strstr(buffer, "output"); + on_start = strchr(on_start, '"'); + on_start++; + char *on_end = strchr(on_start, '"'); + char *outputName = strndup(on_start, on_end - on_start); + // check if the output name is in the descriptions + int i = 0; + while (descriptions[i] != NULL && strcmp(outputName, descriptions[i])) i++; + if (descriptions[i] != NULL) { + profileMatchedNum++; + } else { + // if any output is not matched, break + profileMatchedNum = 0; + ps = Looking_for_profile; + } } - } - break; + break; } } fclose(configFile); @@ -181,10 +161,8 @@ struct profile_line match(char **descriptions, int num, const char *filename) { printf("Matched profile:%s\n", profileName); printf("Start line:%d\nEnd line:%d\n", profileStartLine, profileEndLine); matched_profile.start = profileStartLine; - matched_profile.end = profileEndLine; - } else - dprintf(2, "%s:%i:%s(): Cannot find existing profile to match\n", __FILE__, - __LINE__, __func__); + matched_profile.end = profileEndLine; + } else dprintf(2, "%s:%i:%s(): Cannot find existing profile to match\n", __FILE__, __LINE__, __func__); return matched_profile; } @@ -194,14 +172,10 @@ int wd_store_config(struct wl_list *outputs) { sprintf(tmp_file_name, "%s.tmp", file_name); char *descriptions[HEADS_MAX]; - for (int i = 0; i < HEADS_MAX; i++) { - descriptions[i] = NULL; - } + for (int i = 0; i < HEADS_MAX; i++) descriptions[i] = NULL; char *outputConfigs[HEADS_MAX]; - for (int i = 0; i < HEADS_MAX; i++) { - outputConfigs[i] = (char *)malloc(MAX_NAME_LENGTH); - } + for (int i = 0; i < HEADS_MAX; i++) outputConfigs[i] = (char *)malloc(MAX_NAME_LENGTH); struct wd_head_config *output; int description_index = 0; @@ -209,47 +183,27 @@ int wd_store_config(struct wl_list *outputs) { struct wd_head *head = output->head; // for transform - char* trans_str; + char *trans_str; switch (output->transform) { - case WL_OUTPUT_TRANSFORM_NORMAL: - trans_str = "normal"; - break; - case WL_OUTPUT_TRANSFORM_90: - trans_str = "90"; - break; - case WL_OUTPUT_TRANSFORM_180: - trans_str = "180"; - break; - case WL_OUTPUT_TRANSFORM_270: - trans_str = "270"; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - trans_str = "flipped-90"; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - trans_str = "flipped-180"; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - trans_str = "flipped-270"; - break; - default: - trans_str = "normal"; - break; - } + case WL_OUTPUT_TRANSFORM_NORMAL : trans_str = "normal"; + case WL_OUTPUT_TRANSFORM_90 : trans_str = "90"; + case WL_OUTPUT_TRANSFORM_180 : trans_str = "180"; + case WL_OUTPUT_TRANSFORM_270 : trans_str = "270"; + case WL_OUTPUT_TRANSFORM_FLIPPED_90 : trans_str = "flipped-90"; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: trans_str = "flipped-180"; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: trans_str = "flipped-270"; + default : trans_str = "normal"; + }; if (description_index < HEADS_MAX) { descriptions[description_index] = strdup(head->description); // write output config in given format - sprintf(outputConfigs[description_index], - "output \"%s\" position %d,%d mode %dx%d@%.4f scale %.2f " - "transform %s", - head->description, output->x, output->y, output->width, - output->height, output->refresh / 1.0e3, output->scale, + sprintf(outputConfigs[description_index], "output \"%s\" position %d,%d mode %dx%d@%.4f scale %.2f transform %s", + head->description, output->x, output->y, output->width, output->height, output->refresh / 1.0e3, output->scale, trans_str); description_index++; } else { - dprintf(2, "Too many monitor!\n\t%i is the maximum allowed number", - HEADS_MAX); + dprintf(2, "Too many monitor!\n\t%i is the maximum allowed number", HEADS_MAX); return 1; } } @@ -263,8 +217,7 @@ int wd_store_config(struct wl_list *outputs) { // append new profile FILE *file = fopen(file_name, "a"); if (file == NULL) { - dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, - file_name); + dprintf(2, "%s:%i:%s(): Can't open %s : ", __FILE__, __LINE__, __func__, file_name); perror(NULL); return 1; } @@ -276,7 +229,7 @@ int wd_store_config(struct wl_list *outputs) { fprintf(file, "}"); fclose(file); } else if (matched_profile.start < matched_profile.end) { - // rewrite correspondence lines + // rewrite corresponding lines FILE *file = fopen(file_name, "r"); if (file == NULL) { perror("File open failed."); @@ -284,14 +237,13 @@ int wd_store_config(struct wl_list *outputs) { } FILE *tmp = fopen(tmp_file_name, "w"); if (tmp == NULL) { - dprintf(2, "%s:%i:%s(): Can't create %s : ", __FILE__, __LINE__, __func__, - tmp_file_name); + dprintf(2, "%s:%i:%s(): Can't create %s : ", __FILE__, __LINE__, __func__, tmp_file_name); perror(NULL); fclose(file); return 1; } char _buffer[LINE_MAX]; - int _line = 0; + int _line = 0; int _i_output = 0; while (fgets(_buffer, sizeof(_buffer), file) != NULL) { if (_line >= matched_profile.start && _line < matched_profile.end - 1) { diff --git a/src/wdisplays.h b/src/wdisplays.h index d3da26e..e13f975 100644 --- a/src/wdisplays.h +++ b/src/wdisplays.h @@ -14,7 +14,7 @@ #include "config.h" -#define HEADS_MAX 64 +#define HEADS_MAX 64 #define HOVER_USECS (100 * 1000) #include @@ -110,10 +110,12 @@ struct wd_head { bool enabled; struct wd_mode *mode; + struct { int32_t width, height; int32_t refresh; } custom_mode; + int32_t x, y; enum wl_output_transform transform; double scale; @@ -242,14 +244,12 @@ void wd_fatal_error(int status, const char *message); /* * Add an output to the list of screen captured outputs. */ -void wd_add_output(struct wd_state *state, struct wl_output *wl_output, - struct wl_display *display); +void wd_add_output(struct wd_state *state, struct wl_output *wl_output, struct wl_display *display); /* * Remove an output from the list of screen captured outputs. */ -void wd_remove_output(struct wd_state *state, struct wl_output *wl_output, - struct wl_display *display); +void wd_remove_output(struct wd_state *state, struct wl_output *wl_output, struct wl_display *display); /* * Finds the output associated with a given head. Can return NULL if the head's @@ -264,14 +264,12 @@ struct wd_head *wd_find_head(struct wd_state *state, struct wd_output *output); /* * Starts listening for output management events from the compositor. */ -void wd_add_output_management_listener(struct wd_state *state, - struct wl_display *display); +void wd_add_output_management_listener(struct wd_state *state, struct wl_display *display); /* * Sends updated display configuration back to the compositor. */ -void wd_apply_state(struct wd_state *state, struct wl_list *new_outputs, - struct wl_display *display); +void wd_apply_state(struct wd_state *state, struct wl_list *new_outputs, struct wl_display *display); /* * Queues capture of the next frame of all screens. @@ -319,8 +317,7 @@ struct wd_gl_data *wd_gl_setup(void); /* * Renders the GL scene. */ -void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info, - uint64_t tick); +void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info, uint64_t tick); /* * Destroys the GL shaders. From 2e97de5f56f5a828c6e4e6c0f92d32b80e749edb Mon Sep 17 00:00:00 2001 From: Viorel Munteanu Date: Sat, 28 Dec 2024 11:56:49 +0200 Subject: [PATCH 8/8] Fix C23 issues gcc 15 is more strict and compiles C by default with C23. `noop` is used as a default null initializer, but now it must have the correct type, so add a cast. See also: https://bugs.gentoo.org/946954 --- src/outputs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/outputs.c b/src/outputs.c index 5108f61..f4ac15c 100644 --- a/src/outputs.c +++ b/src/outputs.c @@ -533,7 +533,7 @@ static void output_manager_handle_done(void *data, static const struct zwlr_output_manager_v1_listener output_manager_listener = { .head = output_manager_handle_head, .done = output_manager_handle_done, - .finished = noop, + .finished = (void (*)(void *, struct zwlr_output_manager_v1 *))noop, }; static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { @@ -560,7 +560,7 @@ static void registry_handle_global(void *data, struct wl_registry *registry, static const struct wl_registry_listener registry_listener = { .global = registry_handle_global, - .global_remove = noop, + .global_remove = (void (*)(void *, struct wl_registry *, uint32_t))noop, }; void wd_add_output_management_listener(struct wd_state *state, struct @@ -610,10 +610,10 @@ static void output_name(void *data, struct zxdg_output_v1 *zxdg_output_v1, static const struct zxdg_output_v1_listener output_listener = { .logical_position = output_logical_position, - .logical_size = noop, - .done = noop, + .logical_size = (void (*)(void *, struct zxdg_output_v1 *, int32_t, int32_t))noop, + .done = (void (*)(void *, struct zxdg_output_v1 *))noop, .name = output_name, - .description = noop + .description = (void (*)(void *, struct zxdg_output_v1 *, const char *))noop }; void wd_add_output(struct wd_state *state, struct wl_output *wl_output,