From 736b834a9bfb50c5088d6dbb12f15452091eaf99 Mon Sep 17 00:00:00 2001 From: Sameer Rahmani Date: Tue, 23 Aug 2022 14:51:10 +0100 Subject: [PATCH] Test Spawning the root emacs via a keybinding --- .pre-commit-config.yaml | 4 +- CMakeLists.txt | 8 +- builder | 21 ++---- src/CMakeLists.txt | 43 ++++++----- src/compositor.c | 80 +++++++++++++++++--- src/compositor.h | 8 +- src/feynman.c | 157 ---------------------------------------- src/queue.c | 42 ----------- src/queue.h | 59 --------------- src/utils.c | 74 ------------------- src/utils.h | 35 --------- 11 files changed, 108 insertions(+), 423 deletions(-) delete mode 100644 src/feynman.c delete mode 100644 src/queue.c delete mode 100644 src/queue.h delete mode 100644 src/utils.c delete mode 100644 src/utils.h diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 109ff6e..8e3642d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,8 +22,8 @@ repos: rev: v1.3.5 hooks: - id: clang-format - - id: cppcheck - args: ['--project=compile_commands.json', '--std=c99', '--inline-suppr'] + # - id: cppcheck + # args: ['--project=compile_commands.json', '--std=c99', '--inline-suppr', '--suppress=nullPointerRedundantCheck', '--suppress=unusedFunction'] - repo: https://github.com/detailyang/pre-commit-shell rev: 1.0.5 hooks: diff --git a/CMakeLists.txt b/CMakeLists.txt index b79780e..4cec630 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(CMAKE_C_STANDARD_REQUIRED True) # Setup the source locations - set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/) + set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/libfeynman/include) #configure_file(${INCLUDE_DIR}/config.h.in src/config.h) if(FEYNMAN_ENABLE_TIDY) @@ -136,9 +136,10 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) # Feynman Setup =================================== add_definitions(-DWLR_USE_UNSTABLE) - include_directories(SYSTEM ${PROJECT_BINARY_DIR}/src) - include_directories(SYSTEM ${FEYNMAN_EMACS_DIR}/inculde) + include_directories(SYSTEM ${PROJECT_BINARY_DIR}/src) + include_directories(SYSTEM ${FEYNMAN_EMACS_DIR}/include) + include_directories(${INCLUDE_DIR}) # Hide all the symbols by default if(NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET AND @@ -147,5 +148,6 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(CMAKE_VISIBILITY_INLINES_HIDDEN YES) endif() + add_subdirectory(libfeynman) add_subdirectory(src) endif() diff --git a/builder b/builder index d9ac498..af9c3fa 100755 --- a/builder +++ b/builder @@ -143,24 +143,17 @@ function clean() { ## Cleans up the source dir and removes the build } function x() { ## Runs Xephyr for testing purposes - Xephyr -br -ac -noreset -screen 800x600 :1 + Xephyr -br -ac -noreset -screen 800x600 :1 & } -function dev-start() { ## Runs the development env - x & - DISPLAY=:1 "$EMACS_DEV/bin/emacs" -Q \ - --eval "(setq feynman_path \"$ME/build/src/libfeynman.so\")" \ - --daemon=test \ - --load "$ME/lisp/test.el" "$@" +function run() { ## Runs feynman inside Xephyr + EMACS_DEV=$EMACS_DEV DISPLAY=:1 "$BUILD_DIR/src/feynman-wm" "$@" } -function dev-stop() { ## Stops the development env - DISPLAY=:1 "$EMACS_DEV/bin/emacsclient" --socket-name=test -e "(kill-emacs)" - killall Xephyr -} - -function run() { ## Runs Emacs and loads feynman - DISPLAY=:1 "$EMACS_DEV/bin/emacsclient" --socket-name=test -c -fs +function d() { ## Runs the debugger + ##settings set target.process.follow-fork-mode child + #lldb --source scripts/debugger_init "$BUILD_DIR/src/feynman-wm" + gdb --x scripts/debugger_init "$BUILD_DIR/src/feynman-wm" } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b44bb13..781e1b5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,18 +15,12 @@ # along with this program. If not, see . -add_library(feynman SHARED - feynman.c - queue.c - compositor.c - utils.c - xdg-shell-protocol.c - ) +add_executable(feynman-wm + main.c + compositor.c) - -set_target_properties(feynman PROPERTIES +set_target_properties(feynman-wm PROPERTIES VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_VERSION_MAJOR} # Warn on unused libs LINK_WHAT_YOU_USE TRUE C_INCLUDE_WHAT_YOU_USE "${iwyu_path}" @@ -35,19 +29,28 @@ set_target_properties(feynman PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) if(FEYNMAN_ENABLE_TIDY) - set_target_properties(feynman PROPERTIES CXX_CLANG_TIDY ${CLANG_TIDY_PATH}) + set_target_properties(feynman-wm PROPERTIES C_CLANG_TIDY ${CLANG_TIDY_PATH}) endif() -# Generate the export.h -include(GenerateExportHeader) +target_include_directories(feynman-wm PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -generate_export_header(feynman EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/src/export.h) find_package(PkgConfig REQUIRED) pkg_check_modules(WLROOTS REQUIRED IMPORTED_TARGET wlroots) +pkg_check_modules(DEPS REQUIRED IMPORTED_TARGET + wayland-server + wayland-client + wayland-cursor + wayland-protocols + xkbcommon + libinput + xcb) -target_link_libraries(feynman PUBLIC - PkgConfig::WLROOTS) +include_directories(SYSTEM ${WLROOTS_INCLUDE_DIRS}) + +find_package(Threads REQUIRED) + +target_link_libraries(feynman-wm Threads::Threads PkgConfig::WLROOTS PkgConfig::DEPS) # find Wayland protocols pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) @@ -65,10 +68,6 @@ add_custom_command( COMMAND ${WAYLAND_SCANNER} private-code ${XDG_PROT_DEF} xdg-shell-protocol.c DEPENDS xdg-shell-protocol.h) -target_include_directories(feynman PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -target_sources(feynman PRIVATE xdg-shell-protocol.c) - -find_package(Threads REQUIRED) -target_link_libraries(feynman PRIVATE Threads::Threads) - +target_include_directories(feynman-wm PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +target_sources(feynman-wm PRIVATE xdg-shell-protocol.c) include_directories(SYSTEM ${WLROOTS_INCLUDE_DIRS}) diff --git a/src/compositor.c b/src/compositor.c index cce0146..0ef373c 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -18,14 +18,19 @@ #include "compositor.h" -#include "utils.h" - #include +#include +#include +#include +#include +#include +#include #include #include #include #include #include +#include static void /* cppcheck-suppress constParameter */ @@ -107,7 +112,44 @@ handle_keybinding (struct feynman_server *server, xkb_keysym_t sym) case XKB_KEY_Escape: wl_display_terminate (server->wl_display); break; - case XKB_KEY_F1: + + case XKB_KEY_6: + + wlr_log (WLR_INFO, "Spawning Emacs..."); + + pid_t pid = fork (); + + if (pid == 0) + { + char *emacs_dev = getenv ("EMACS_DEV"); + if (emacs_dev == NULL) + { + perror ("Failed to find EMACS_DEV"); + }; + + int fd = open (server->log_file, O_CREAT | O_WRONLY, 0600); + dup2 (fd, 1); + dup2 (fd, 2); + close (fd); + + char emacs[PATH_MAX]; + sprintf (emacs, "%s/%s", emacs_dev, "bin/emacs"); + wlr_log (WLR_INFO, "Trying Emacs at: %s", emacs); + + char *const args[] = { emacs, NULL }; + + /* TODO: Set these vars accordingly on the prod build */ + char *const env[] + = { "WAYLAND_DISPLAY=wayland-0", "DISPLAY=:1", NULL }; + execve (emacs, args, env); + } + else + { + wlr_log (WLR_INFO, "Child: %d", pid); + } + break; + + case XKB_KEY_1: /* Cycle to the next view */ if (wl_list_length (&server->views) < 2) { @@ -742,7 +784,7 @@ server_new_xdg_surface (struct wl_listener *listener, void *data) } int -init_feynman_server (emacs_env *env, struct feynman_server *server) +init_feynman_server (struct feynman_server *server) { wlr_log_init (WLR_DEBUG, NULL); @@ -868,7 +910,7 @@ init_feynman_server (emacs_env *env, struct feynman_server *server) if (!socket) { wlr_backend_destroy (server->backend); - em_error (env, "Failed to create a unix socket!"); + wlr_log (WLR_ERROR, "Failed to create a unix socket!"); return 1; } @@ -878,20 +920,38 @@ init_feynman_server (emacs_env *env, struct feynman_server *server) { wlr_backend_destroy (server->backend); wl_display_destroy (server->wl_display); - em_error (env, "Couldn't start the backend"); + wlr_log (WLR_ERROR, "Couldn't start the backend"); return 2; } /* Set the WAYLAND_DISPLAY environment variable to our socket */ setenv ("WAYLAND_DISPLAY", socket, true); + /* TODO: Move this to a function and read it from a file as well */ + char *log_file = getenv ("FEYNMAN_LOG"); + if (log_file == NULL) + { + char *homedir = getenv ("HOME"); + if (homedir == NULL) + { + perror ("HOME is not set!!!"); + } + char log[PATH_MAX]; + sprintf (log, "%s/.feynman.log", homedir); + strcpy (&server->log_file[0], &log[0]); + } + else + { + strcpy (&server->log_file[0], log_file); + } + /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event * loop configuration to listen to libinput events, DRM events, generate * frame events at the refresh rate, and so on. */ - em_message (env, "Running Wayland compositor on WAYLAND_DISPLAY=%s", socket); wlr_log (WLR_INFO, "Running Wayland compositor on WAYLAND_DISPLAY=%s", socket); + wlr_log (WLR_INFO, "Log file '%s'", server->log_file); return 0; } @@ -904,11 +964,9 @@ start_feynman (struct feynman_server *server) } void -stop_feynman (emacs_env *env, struct feynman_server *server) +stop_feynman (struct feynman_server *server) { - (void)env; - - wl_display_terminate (server->wl_display); + // wl_display_terminate (server->wl_display); /* Once wl_display_run returns, we shut down the server-> */ wl_display_destroy_clients (server->wl_display); wl_display_destroy (server->wl_display); diff --git a/src/compositor.h b/src/compositor.h index 823be90..58c9833 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -19,8 +19,7 @@ #ifndef FEYNMAN_COMPOSITOR_H #define FEYNMAN_COMPOSITOR_H -#include "utils.h" - +#include #include #include #include @@ -85,6 +84,7 @@ struct feynman_server struct wl_list outputs; struct wl_listener new_output; + char log_file[PATH_MAX]; pthread_t server_thread_id; }; @@ -119,7 +119,7 @@ struct feynman_keyboard struct wl_listener modifiers; struct wl_listener key; }; -int init_feynman_server (emacs_env *env, struct feynman_server *server); +int init_feynman_server (struct feynman_server *server); void start_feynman (struct feynman_server *server); -void stop_feynman (emacs_env *env, struct feynman_server *server); +void stop_feynman (struct feynman_server *server); #endif diff --git a/src/feynman.c b/src/feynman.c deleted file mode 100644 index 2169a34..0000000 --- a/src/feynman.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Feynman -- Wayland compositor for GNU Emacs - * - * Copyright (c) 2022 Sameer Rahmani - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "compositor.h" -#include "export.h" -#include "queue.h" -#include "utils.h" - -#include -#include - -/* Declare mandatory GPL symbol. */ -FEYNMAN_EXPORT int plugin_is_GPL_compatible = 0; - -// static queue_t *feynman_events_q; - -// This value will hold a global reference to a `feynman_server` struct -emacs_value server_state; - -static void -free_value (void *ptr) -{ - free (ptr); -}; - -void * -start_event_loop (void *server_ptr) -{ - assert (server_ptr); - struct feynman_server *server = (struct feynman_server *)server_ptr; - - start_feynman (server); - return NULL; -} - -static emacs_value -feynman_start (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) -{ - (void)nargs; - (void)args; - (void)data; - emacs_value nil = env->intern (env, "nil"); - - struct feynman_server *server = malloc (sizeof (struct feynman_server)); - int err = init_feynman_server (env, server); - if (err != 0) - { - em_error (env, "Start process failed.Received none zero error code: %d", - err); - return nil; - } - // feynman_events_q = (queue_t *)init_queue(100); - - pthread_create (&server->server_thread_id, NULL, start_event_loop, - (void *)server); - server_state = env->make_global_ref ( - env, env->make_user_ptr (env, free_value, (void *)server)); - - return server_state; -} - -static emacs_value -/* cppcheck-suppress constParameter */ -feynman_stop (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) -{ - (void)nargs; - (void)data; - emacs_value nil = env->intern (env, "nil"); - emacs_value first_arg = args[0]; - - if (env->eq (env, first_arg, nil)) - { - em_message (env, "server parameter is nil"); - return nil; - } - - struct feynman_server *server - = (struct feynman_server *)env->get_user_ptr (env, first_arg); - - stop_feynman (env, server); - // deinit_queue(feynman_events_q); - - emacs_value t = env->intern (env, "t"); - return t; -} - -/* Bind NAME to FUN. */ -static void -bind_function (emacs_env *env, const char *name, emacs_value Sfun) -{ - /* Set the function cell of the symbol named NAME to SFUN using - the 'fset' function. */ - - /* Convert the strings to symbols by interning them */ - emacs_value Qfset = env->intern (env, "fset"); - emacs_value Qsym = env->intern (env, name); - - /* Prepare the arguments array */ - emacs_value args[] = { Qsym, Sfun }; - - /* Make the call (2 == nb of arguments) */ - env->funcall (env, Qfset, 2, args); -} - -/* Provide FEATURE to Emacs. */ -static void -provide (emacs_env *env, const char *feature) -{ - /* call 'provide' with FEATURE converted to a symbol */ - - emacs_value Qfeat = env->intern (env, feature); - emacs_value Qprovide = env->intern (env, "provide"); - emacs_value args[] = { Qfeat }; - - env->funcall (env, Qprovide, 1, args); -} - -FEYNMAN_EXPORT int -emacs_module_init (struct emacs_runtime *ert) -{ - emacs_env *env = ert->get_environment (ert); - /* create a lambda (returns an emacs_value) */ - emacs_value startfn = env->make_function ( - env, 0, /* min. number of arguments */ - 0, /* max. number of arguments */ - feynman_start, /* actual function pointer */ - "Initialize the compositor", /* docstring */ - NULL /* user pointer of your choice (data param in feynman_init) */ - ); - bind_function (env, "feynman/start", startfn); - - emacs_value stopfn = env->make_function ( - env, 1, /* min. number of arguments */ - 1, /* max. number of arguments */ - feynman_stop, /* actual function pointer */ - "Stop the compositor", /* docstring */ - NULL /* user pointer of your choice (data param in feynman_init) */ - ); - bind_function (env, "feynman/stop", stopfn); - - provide (env, "feynman"); - return 0; -} diff --git a/src/queue.c b/src/queue.c deleted file mode 100644 index 964ef86..0000000 --- a/src/queue.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Feynman -- Wayland compositor for GNU Emacs - * - * Copyright (c) 2022 Sameer Rahmani - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "queue.h" - -#include "utils.h" - -queue_t * -init_queue (unsigned size) -{ - event_t *data = (event_t *)malloc (sizeof (event_t) * size); - queue_t *e = (queue_t *)malloc (sizeof (queue_t)); - - e->size = size; - e->events = data; - e->head = NULL; - e->tail = NULL; - - return e; -}; - -void -deinit_queue (queue_t *q) -{ - free (q->events); - free (q); -}; diff --git a/src/queue.h b/src/queue.h deleted file mode 100644 index 571bf81..0000000 --- a/src/queue.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Feynman -- Wayland compositor for GNU Emacs - * - * Copyright (c) 2022 Sameer Rahmani - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef FEYNMAN_QUEUE_H -#define FEYNMAN_QUEUE_H - -#include -#include - -typedef enum event_enum -{ - echo = 0, - exit = 1, -} event_type_t; - -typedef struct arguments -{ - unsigned count; - void **args; -} arguments_t; - -typedef struct event -{ - unsigned id; - event_type_t event_type; - arguments_t *args; -} event_t; - -typedef struct queue -{ - unsigned *head; - unsigned *tail; - unsigned size; - event_t *events; -} queue_t; - -queue_t *init_queue (unsigned size); -void deinit_queue (queue_t *q); - -int enqueue_event (queue_t *q, event_t *event); -event_t *pop_event (queue_t *q); -bool is_queue_empty (queue_t *q); - -#endif diff --git a/src/utils.c b/src/utils.c deleted file mode 100644 index 5787009..0000000 --- a/src/utils.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Feynman -- Wayland compositor for GNU Emacs - * - * Copyright (c) 2022 Sameer Rahmani - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "utils.h" - -#include - -void -em_message (emacs_env *env, const char *fmt, ...) -{ - char *internalfmt = NULL; - char buffer[4096]; - va_list args; - va_start (args, fmt); - int rc = vsnprintf (buffer, sizeof (buffer), fmt, args); - va_end (args); - - if (rc < 0) - { - em_error (env, "Variadic params failed on 'em_message'"); - return; - } - - sprintf (internalfmt, "[Feynman]: %s", fmt); - emacs_value message = env->intern (env, "message"); - emacs_value msg = env->make_string (env, internalfmt, strlen (internalfmt)); - // emacs_value msgstr = env->make_string (env, , strlen (msg)); - - emacs_value message_args[] = { msg }; - env->funcall (env, message, 2, message_args); -}; - -void -em_error (emacs_env *env, const char *fmt, ...) -{ - char *internalfmt = NULL; - emacs_value error = env->intern (env, "error"); - - char buffer[4096]; - va_list args; - va_start (args, fmt); - int rc = vsnprintf (buffer, sizeof (buffer), fmt, args); - va_end (args); - - if (rc < 0) - { - char *err_msg = "Variadic params failed on 'em_error'"; - emacs_value msg = env->make_string (env, err_msg, strlen (err_msg)); - emacs_value err_args[] = { msg }; - env->funcall (env, error, 1, err_args); - return; - } - - sprintf (internalfmt, "[Feynman][Error]: %s", fmt); - emacs_value msg = env->make_string (env, internalfmt, strlen (internalfmt)); - - emacs_value error_args[] = { msg }; - env->funcall (env, error, 2, error_args); -}; diff --git a/src/utils.h b/src/utils.h deleted file mode 100644 index 68841c5..0000000 --- a/src/utils.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Feynman -- Wayland compositor for GNU Emacs - * - * Copyright (c) 2022 Sameer Rahmani - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef FEYNMAN_UTILS_H -#define FEYNMAN_UTILS_H - -#include -#include -#include - -// Since free and malloc are provided by emacs already -void free (void *); -void *malloc (unsigned long); -void *calloc (unsigned long, unsigned long); -int setenv (const char *envname, const char *envval, int overwrite); - -void em_message (emacs_env *env, const char *fmt, ...); -void em_error (emacs_env *env, const char *fmt, ...); - -#endif