From 2fa5164cb66952038e5081cbefb0775e5799da13 Mon Sep 17 00:00:00 2001 From: klemek Date: Fri, 12 Sep 2025 11:26:17 +0200 Subject: [PATCH] select screen --- README.md | 5 +++-- src/args.c | 63 +++++++++++++++++++++++++++++++++++++++++++---------- src/args.h | 2 +- src/forge.c | 39 ++++++++++++++++++++++++++++----- src/forge.h | 2 +- src/main.c | 2 +- src/types.h | 8 +++---- 7 files changed, 93 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 7985c21..79903a4 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Fusion Of Real-time Generative Effects. options: --help show this help message and exit -v, --version print version + -s, --screen output screen number (default: primary) ``` ## Release guide @@ -89,8 +90,8 @@ make -f Makefile.dev release-arch - [ ] Handle compilation errors - [ ] Minimal working fragment sample - [ ] Hot-reload fragment shader - - [ ] Force fullscreen - - [ ] Select screen as argument + - [x] Force fullscreen + - [ ] Select screen as argument / config - [ ] Midi - [ ] Read Midi events - [ ] Read midi mapping config file diff --git a/src/args.c b/src/args.c index 3972b87..cc11b9c 100644 --- a/src/args.c +++ b/src/args.c @@ -6,21 +6,29 @@ #include void print_help(int status_code) { - puts(PACKAGE " " VERSION "\n\n" - "usage: " PACKAGE " " - "[--help] " - "[-v] " - "\n\n" - "Fusion Of Real-time Generative Effects.\n\n" - "options:\n" - " --help show this help message and exit\n" - " -v, --version print version\n"); + puts(PACKAGE + " " VERSION "\n\n" + "usage: " PACKAGE " " + "[--help] " + "[-v] " + "[-s=SCREEN] " + "\n\n" + "Fusion Of Real-time Generative Effects.\n\n" + "options:\n" + " --help show this help message and exit\n" + " -v, --version print version\n" + " -s, --screen output screen number (default: primary)\n"); exit(status_code); } void invalid_arg(char *arg) { fprintf(stderr, "invalid argument: '%s'\n\n", arg); - print_help(EXIT_FAILURE); + print_help(1); +} + +void invalid_value(char *arg, char *value) { + fprintf(stderr, "invalid value for argument '%s': '%s'\n\n", arg, value); + print_help(1); } bool is_arg(char *arg, char *ref) { return strcoll(arg, ref) == 0; } @@ -30,8 +38,37 @@ char *split_arg_value(char *arg) { return strtok(NULL, "="); } -parameters parse_args(int argc, char **argv) { - parameters params; +bool is_digit(char c) { return c >= '0' && c <= '9'; } + +bool is_number(char *value) { + if (value == NULL) { + return false; + } + unsigned long value_len = strlen(value); + unsigned int i; + for (i = 0; i < value_len; i++) { + if (!is_digit(value[i])) { + return false; + } + } + return true; +} + +unsigned char parse_uchar(char *arg, char *value) { + if (!is_number(value)) { + invalid_value(arg, value); + } + unsigned long long tmp_value = (unsigned long long)atoll(value); + if (tmp_value >= 256) { + invalid_value(arg, value); + } + return (unsigned char)tmp_value; +} + +Parameters parse_args(int argc, char **argv) { + Parameters params; + + params.screen = 0; int i; char *arg; @@ -44,6 +81,8 @@ parameters parse_args(int argc, char **argv) { } else if (is_arg(arg, "-v") || is_arg(arg, "--version")) { puts(PACKAGE " " VERSION); exit(EXIT_SUCCESS); + } else if (is_arg(arg, "-s") || is_arg(arg, "--screen")) { + params.screen = parse_uchar(arg, value); } else { invalid_arg(arg); } diff --git a/src/args.h b/src/args.h index bb1dd73..85774b7 100644 --- a/src/args.h +++ b/src/args.h @@ -3,6 +3,6 @@ #ifndef ARGS_H #define ARGS_H -parameters parse_args(int argc, char **argv); +Parameters parse_args(int argc, char **argv); #endif \ No newline at end of file diff --git a/src/forge.c b/src/forge.c index 196d990..e9bf7f1 100644 --- a/src/forge.c +++ b/src/forge.c @@ -45,42 +45,69 @@ static const char *fragment_shader_text = void error_callback(int error, const char *description) { fprintf(stderr, "Error %d: %s\n", error, description); + glfwTerminate(); + exit(EXIT_FAILURE); } static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) { + // close window on escape key if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { glfwSetWindowShouldClose(window, GLFW_TRUE); } } -void *init_window(GLFWwindow **window) { +void *init_window(GLFWwindow **window, Parameters params) { + // set errors handler glfwSetErrorCallback(error_callback); + // print current GLFW version fprintf(stdout, "[GLFW] %s\n", glfwGetVersionString()); + // init GLFW if (!glfwInit()) { fprintf(stderr, "[GLFW] Initialization failed\n"); exit(EXIT_FAILURE); } + // add context to window before creation glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_DECORATED, NULL); + glfwWindowHint(GLFW_DECORATED, 0); - (*window) = glfwCreateWindow(640, 480, PACKAGE " " VERSION, - glfwGetPrimaryMonitor(), NULL); + // detect monitors + int count; + GLFWmonitor **monitors = glfwGetMonitors(&count); + // check selected monitor availability + if (params.screen >= count) { + fprintf(stderr, "Screen %d is out of range [0-%d]\n", params.screen, + count - 1); + glfwTerminate(); + exit(EXIT_FAILURE); + } + + // create fullscreen window in selected monitor + (*window) = glfwCreateWindow(1, 1, PACKAGE " " VERSION, + monitors[params.screen], NULL); + + // handle window creation fail if (!(*window)) { fprintf(stderr, "[GLFW] Window or context creation failed\n"); glfwTerminate(); exit(EXIT_FAILURE); } + // use current window glfwMakeContextCurrent((*window)); + // link GLAD and GLFW window gladLoadGL(glfwGetProcAddress); + // set keyboard handler glfwSetKeyCallback((*window), key_callback); + // hide cursor + glfwSetInputMode((*window), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + // vsync glfwSwapInterval(1); return window; @@ -144,10 +171,10 @@ void loop(GLFWwindow *window, ShaderProgram program) { glfwPollEvents(); } -void forge_run(parameters params) { +void forge_run(Parameters params) { GLFWwindow *window; - init_window(&window); + init_window(&window, params); ShaderProgram program = init_program(); diff --git a/src/forge.h b/src/forge.h index 3dafa75..fe46c86 100644 --- a/src/forge.h +++ b/src/forge.h @@ -3,6 +3,6 @@ #ifndef FORGE_H #define FORGE_H -void forge_run(parameters params); +void forge_run(Parameters params); #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index d5d4e0b..d881353 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,7 @@ #include int main(int argc, char **argv) { - parameters params; + Parameters params; params = parse_args(argc, argv); puts(PACKAGE " " VERSION); forge_run(params); diff --git a/src/types.h b/src/types.h index 291b450..e4874eb 100644 --- a/src/types.h +++ b/src/types.h @@ -4,9 +4,9 @@ #ifndef TYPES_H #define TYPES_H -struct Parameters { - // TODO -}; +typedef struct Parameters { + unsigned char screen; +} Parameters; typedef struct Vertex { vec2 pos; @@ -28,6 +28,4 @@ typedef struct ShaderProgram { GLuint vertex_array; } ShaderProgram; -typedef struct Parameters parameters; - #endif \ No newline at end of file