diff options
-rw-r--r-- | meson.build | 5 | ||||
-rw-r--r-- | src/AglShellGrpcClient.cpp | 18 | ||||
-rw-r--r-- | src/AglShellGrpcClient.h | 18 | ||||
-rw-r--r-- | src/main.cpp | 176 |
4 files changed, 145 insertions, 72 deletions
diff --git a/meson.build b/meson.build index 321f130..bd00929 100644 --- a/meson.build +++ b/meson.build @@ -3,7 +3,8 @@ project('agl-shell-activator', version: '0.0.2', default_options: [ 'warning_level=3', - 'c_std=gnu99', + 'c_std=c2x', + 'cpp_std=c++20' ], meson_version: '>= 0.60', license: 'MIT/Expat', @@ -63,8 +64,6 @@ srcs_agl_activator = [ 'src/AglShellGrpcClient.h', generated_protoc_sources, generated_grpc_sources, - agl_shell_desktop_client_protocol_h, - agl_shell_desktop_protocol_c, ] exe_wth_receiver = executable( diff --git a/src/AglShellGrpcClient.cpp b/src/AglShellGrpcClient.cpp index fb8ebbe..0840d28 100644 --- a/src/AglShellGrpcClient.cpp +++ b/src/AglShellGrpcClient.cpp @@ -45,6 +45,20 @@ GrpcClient::ActivateApp(const std::string& app_id, const std::string& output_nam return status.ok(); } +bool +GrpcClient::DeactivateApp(const std::string& app_id) +{ + agl_shell_ipc::DeactivateRequest request; + + request.set_app_id(app_id); + + grpc::ClientContext context; + ::agl_shell_ipc::DeactivateResponse reply; + + grpc::Status status = m_stub->DeactivateApp(&context, request, &reply); + return status.ok(); +} + grpc::Status GrpcClient::Wait(void) { @@ -52,7 +66,7 @@ GrpcClient::Wait(void) } void -GrpcClient::AppStatusState(void) +GrpcClient::AppStatusState(Callback callback) { - reader->AppStatusState(); + reader->AppStatusState(callback); } diff --git a/src/AglShellGrpcClient.h b/src/AglShellGrpcClient.h index 009bfbf..50531f9 100644 --- a/src/AglShellGrpcClient.h +++ b/src/AglShellGrpcClient.h @@ -15,6 +15,8 @@ #include "agl_shell.grpc.pb.h" +typedef void (*Callback)(agl_shell_ipc::AppStateResponse app_response); + class Reader : public grpc::ClientReadReactor<::agl_shell_ipc::AppStateResponse> { public: Reader(agl_shell_ipc::AglShellManagerService::Stub *stub) @@ -22,9 +24,12 @@ public: { } - void AppStatusState() + void AppStatusState(Callback callback) { ::agl_shell_ipc::AppStateRequest request; + + // set up the callback + m_callback = callback; m_stub->async()->AppStatusState(&m_context, &request, this); StartRead(&m_app_state); @@ -34,10 +39,7 @@ public: void OnReadDone(bool ok) override { if (ok) { - std::cout << "AppState got app_id " << - m_app_state.app_id() << - ", with state " << - m_app_state.state() << std::endl; + m_callback(m_app_state); // blocks in StartRead() if the server doesn't send // antyhing @@ -76,6 +78,9 @@ private: ::agl_shell_ipc::AppStateResponse m_app_state; agl_shell_ipc::AglShellManagerService::Stub *m_stub; + Callback m_callback; + + std::mutex m_mutex; std::condition_variable m_cv; grpc::Status m_status; @@ -86,8 +91,9 @@ class GrpcClient { public: GrpcClient(); bool ActivateApp(const std::string& app_id, const std::string& output_name); + bool DeactivateApp(const std::string& app_id); void GetAppState(); - void AppStatusState(); + void AppStatusState(Callback callback); grpc::Status Wait(); private: diff --git a/src/main.cpp b/src/main.cpp index 2df7421..7ebde3b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,13 +30,44 @@ #include <assert.h> #include <thread> +#include <unistd.h> #include <wayland-client.h> #include <wayland-util.h> +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) +#endif + #include "AglShellGrpcClient.h" -static int running = 1; -const char *app_id_to_activate = NULL; +enum action_state { + NONE = -1, + ACTIVATE, + DEACTIVATE, + SET_FLOAT, + SET_SPLIT, +}; + +static struct action { + enum action_state action; + const char *name; +} actions[] = { + { ACTIVATE, "ACTIVATE" }, + { DEACTIVATE, "DEACTIVATE" }, +}; + +static int +get_action(const char *action_name) +{ + size_t i; + + for (i = 0; i < ARRAY_LENGTH(actions); i++) { + if (action_name && strcasecmp(action_name, actions[i].name) == 0) + return actions[i].action; + } + + return -1; +} static void run_in_thread(GrpcClient *client) @@ -44,77 +75,100 @@ run_in_thread(GrpcClient *client) grpc::Status status = client->Wait(); } -int main(int argc, char *argv[]) +static void +help(char **argv) { - struct display *display; - struct window_output *w_output = NULL; - char *output_name = NULL; - int ret = 0; - bool use_grpc_activation = false; + fprintf(stderr, "Usage: %s [-a action] [-p app_id] [-o output_name] [-l]\n", + argv[0]); + exit(EXIT_FAILURE); +} - if (argc < 2) { - exit(EXIT_FAILURE); - } +static void +app_status_callback(::agl_shell_ipc::AppStateResponse app_response) +{ + std::cout << " >> AppStateResponse app_id " << + app_response.app_id() << ", with state " << + app_response.state() << std::endl; +} - if (argc == 3) { - output_name = argv[2]; +int main(int argc, char *argv[]) +{ + char *output = NULL; + char *action = NULL; + char *app_id = NULL; + int opt; + bool listen_flag = false; + std::thread th; + + // app_id, output p[0] -> name, p[1] action, p[2] app_id, p[3] -> output + while ((opt = getopt(argc, argv, "a:p:o:lh")) != -1) { + switch (opt) { + case 'p': + app_id = optarg; + break; + case 'a': + action = optarg; + break; + case 'o': + output = optarg; + break; + case 'l': + listen_flag = true; + break; + case 'h': + default: /* '?' */ + help(argv); + } } - if (argc == 4 && strcmp(argv[3], "use-grpc") == 0) - use_grpc_activation = true; - - - display = create_display(); - - /* the app has to be already started, or not already active */ - app_id_to_activate = argv[1]; - if (app_id_to_activate && strlen(app_id_to_activate) == 0) + if (!action && !listen_flag) { + help(argv); exit(EXIT_FAILURE); - - if (output_name) { - struct window_output *woutput; - - wl_list_for_each(woutput, &display->output_list, link) { - if (woutput->name && !strcmp(woutput->name, output_name)) { - w_output = woutput; - break; - } - } - } else { - w_output = wl_container_of(display->output_list.prev, w_output, link); } - /* maybe that output doesn't exit, still allow a fallback */ - if (!w_output) - w_output = wl_container_of(display->output_list.prev, w_output, link); - - fprintf(stderr, "Activating application '%s' on output '%s'\n", - app_id_to_activate, w_output->name ? - w_output->name : "first default output"); + // start grpc connection + GrpcClient *client = new GrpcClient(); - if (use_grpc_activation) { - fprintf(stderr, "using grpc\n"); - GrpcClient *client = new GrpcClient(); - - // this blocks in wait - std::thread thread(run_in_thread, client); - - // this does the actually call to get events - client->AppStatusState(); - - client->ActivateApp(std::string(app_id_to_activate), - std::string(w_output->name)); - thread.join(); - } else { - fprintf(stderr, "using agl_shell_desktop\n"); - agl_shell_desktop_activate_app(display->agl_shell_desktop, - app_id_to_activate, NULL, w_output->output); + if (listen_flag) { + fprintf(stderr, "Listening for events...\n"); + th = std::thread(run_in_thread, client); + client->AppStatusState(app_status_callback); + } - while (running && ret != -1) { - ret = wl_display_dispatch(display->display); + switch (get_action(action)) { + case ACTIVATE: + if (!output && !app_id) { + fprintf(stderr, "Activation require both an app_id and an output\n"); + help(argv); } + fprintf(stderr, "Activating application '%s' on output '%s'\n", + app_id, output); + client->ActivateApp(std::string(app_id), std::string(output)); + break; + case DEACTIVATE: + if (!app_id) { + fprintf(stderr, "Deactivation require an app_id\n"); + help(argv); + } + fprintf(stderr, "Deactivating application '%s'\n", app_id); + client->DeactivateApp(std::string(app_id)); + break; + default: + // allow listen flag to be passed + if (listen_flag) + break; + + fprintf(stderr, "Unknown action passed. Possible actions:\n\t"); + for (size_t i = 0; ARRAY_LENGTH(actions); i++) + fprintf(stderr, " %s ", actions[i].name); + + help(argv); + break; + } + + if (listen_flag) { + th.join(); } - destroy_display(display); return 0; } |