Add kiwmic IPC

This commit is contained in:
buffet 2020-01-03 18:40:11 +00:00
parent cbe587b8c2
commit b79aa962d6
10 changed files with 313 additions and 2 deletions

18
include/luak/ipc.h Normal file
View file

@ -0,0 +1,18 @@
/* Copyright (c), Charlotte Meyer <dev@buffet.sh>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef KIWMI_LUAK_IPC_H
#define KIWMI_LUAK_IPC_H
#include <stdbool.h>
#include "luak/luak.h"
#include "server.h"
bool luaK_ipc_init(struct kiwmi_server *server, struct kiwmi_lua *lua);
#endif /* KIWMI_LUAK_IPC_H */

View file

@ -17,6 +17,7 @@
struct kiwmi_lua {
lua_State *L;
struct wl_list callbacks; // lua_callback::link
struct wl_global *global;
};
int luaK_callback_register_dispatch(lua_State *L);

92
kiwmi/luak/ipc.c Normal file
View file

@ -0,0 +1,92 @@
/* Copyright (c), Charlotte Meyer <dev@buffet.sh>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "luak/ipc.h"
#include <lauxlib.h>
#include <wlr/util/log.h>
#include "kiwmi-ipc-server-protocol.h"
#include "luak/luak.h"
static void
ipc_eval(
struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
const char *message)
{
struct kiwmi_server *server = wl_resource_get_user_data(resource);
struct wl_resource *command_resource =
wl_resource_create(client, &kiwmi_command_interface, 1, id);
lua_State *L = server->lua->L;
int top = lua_gettop(L);
if (luaL_dostring(L, message)) {
const char *error = lua_tostring(L, -1);
wlr_log(WLR_ERROR, "Error running IPC command: %s", error);
kiwmi_command_send_done(
command_resource, KIWMI_COMMAND_ERROR_FAILURE, error);
return;
}
int results = top - lua_gettop(L);
if (results == 0) {
kiwmi_command_send_done(
command_resource, KIWMI_COMMAND_ERROR_SUCCESS, "");
} else {
kiwmi_command_send_done(
command_resource, KIWMI_COMMAND_ERROR_SUCCESS, lua_tostring(L, -1));
}
}
static const struct kiwmi_ipc_interface kiwmi_ipc_implementation = {
.eval = ipc_eval,
};
static void
kiwmi_server_resource_destroy(struct wl_resource *UNUSED(resource))
{
// EMPTY
}
static void
ipc_server_bind(
struct wl_client *client,
void *data,
uint32_t version,
uint32_t id)
{
struct kiwmi_server *server = data;
struct wl_resource *resource =
wl_resource_create(client, &kiwmi_ipc_interface, version, id);
if (!resource) {
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(
resource,
&kiwmi_ipc_implementation,
server,
kiwmi_server_resource_destroy);
}
bool
luaK_ipc_init(struct kiwmi_server *server, struct kiwmi_lua *lua)
{
lua->global = wl_global_create(
server->wl_display, &kiwmi_ipc_interface, 1, server, ipc_server_bind);
if (!lua->global) {
wlr_log(WLR_ERROR, "Failed to create IPC global");
return false;
}
return true;
}

View file

@ -13,6 +13,7 @@
#include <lualib.h>
#include <wlr/util/log.h>
#include "luak/ipc.h"
#include "luak/kiwmi_lua_callback.h"
#include "luak/kiwmi_server.h"
#include "luak/kiwmi_view.h"
@ -54,6 +55,7 @@ luaK_create(struct kiwmi_server *server)
lua_State *L = luaL_newstate();
if (!L) {
free(lua);
return NULL;
}
@ -71,6 +73,8 @@ luaK_create(struct kiwmi_server *server)
if (error) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_close(L);
free(lua);
return NULL;
}
@ -79,6 +83,8 @@ luaK_create(struct kiwmi_server *server)
lua_pushlightuserdata(L, server);
if (lua_pcall(L, 1, 1, 0)) {
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
lua_close(L);
free(lua);
return NULL;
}
lua_setglobal(L, "kiwmi");
@ -87,6 +93,13 @@ luaK_create(struct kiwmi_server *server)
wl_list_init(&lua->callbacks);
if (!luaK_ipc_init(server, lua)) {
wlr_log(WLR_ERROR, "Failed to initialize IPC");
lua_close(L);
free(lua);
return NULL;
}
return lua;
}

View file

@ -8,6 +8,7 @@ kiwmi_sources = files(
'input/cursor.c',
'input/input.c',
'input/keyboard.c',
'luak/ipc.c',
'luak/kiwmi_lua_callback.c',
'luak/kiwmi_server.c',
'luak/kiwmi_view.c',

103
kiwmic/main.c Normal file
View file

@ -0,0 +1,103 @@
/* Copyright (c), Charlotte Meyer <dev@buffet.sh>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include "kiwmi-ipc-client-protocol.h"
static void
command_done(
void *data,
struct kiwmi_command *UNUSED(kiwmi_command),
uint32_t error,
const char *message)
{
int *exit_code = data;
FILE *out;
if (error == KIWMI_COMMAND_ERROR_SUCCESS) {
*exit_code = EXIT_SUCCESS;
out = stdout;
} else {
*exit_code = EXIT_FAILURE;
out = stderr;
}
if (message[0] != '\0') {
fprintf(out, "%s\n", message);
}
}
static const struct kiwmi_command_listener command_listener = {
.done = command_done,
};
static void
registry_global(
void *data,
struct wl_registry *registry,
uint32_t name,
const char *interface,
uint32_t UNUSED(version))
{
struct kiwmi_ipc **ipc = data;
if (strcmp(interface, kiwmi_ipc_interface.name) == 0) {
*ipc = wl_registry_bind(registry, name, &kiwmi_ipc_interface, 1);
}
}
static void
registry_global_remove(
void *UNUSED(data),
struct wl_registry *UNUSED(registry),
uint32_t UNUSED(name))
{
// EMPTY
}
static const struct wl_registry_listener registry_listener = {
.global = registry_global,
.global_remove = registry_global_remove,
};
int
main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: kiwmic COMMAND\n");
exit(EXIT_FAILURE);
}
struct wl_display *display = wl_display_connect(NULL);
if (!display) {
fprintf(stderr, "Failed to connect to display\n");
exit(EXIT_FAILURE);
}
struct wl_registry *registry = wl_display_get_registry(display);
struct kiwmi_ipc *ipc = NULL;
wl_registry_add_listener(registry, &registry_listener, &ipc);
wl_display_roundtrip(display);
if (!ipc) {
fprintf(stderr, "Failed to bind to kiwmi_ipc\n");
exit(EXIT_FAILURE);
}
struct kiwmi_command *command = kiwmi_ipc_eval(ipc, argv[1]);
int exit_code;
kiwmi_command_add_listener(command, &command_listener, &exit_code);
wl_display_roundtrip(display);
wl_display_disconnect(display);
exit(exit_code);
}

16
kiwmic/meson.build Normal file
View file

@ -0,0 +1,16 @@
kiwmic_sources = files(
'main.c',
)
kiwmic_deps = [
protocols_client,
wayland_client,
]
executable(
'kiwmic',
kiwmic_sources,
include_directories: [include],
dependencies: kiwmic_deps,
install: true,
)

View file

@ -18,6 +18,7 @@ add_project_arguments(
git = find_program('git', required: false)
lua = dependency('lua')
wayland_client = dependency('wayland-client')
wayland_protocols = dependency('wayland-protocols')
wayland_scanner = dependency('wayland-scanner')
wayland_server = dependency('wayland-server')
@ -49,3 +50,4 @@ endif
subdir('protocols')
subdir('kiwmi')
subdir('kiwmic')

31
protocols/kiwmi-ipc.xml Normal file
View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="kiwmi_ipc">
<copyright>
Copyright (c), Charlotte Meyer &lt;dev@buffet.sh&gt;
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this file,
You can obtain one at https://mozilla.org/MPL/2.0/.
</copyright>
<interface name="kiwmi_ipc" version="1">
<request name="eval">
<description summary="evaluate a given Lua snippet" />
<arg name="id" type="new_id" interface="kiwmi_command" />
<arg name="command" type="string" />
</request>
</interface>
<interface name="kiwmi_command" version="1">
<enum name="error">
<entry name="success" value="0" summary="the command ran successfully" />
<entry name="failure" value="1" summary="the command did not run successfully" />
</enum>
<event name="done">
<arg name="error" type="uint" />
<arg name="message" type="string" summary="error message or return value" />
</event>
</interface>
</protocol>

View file

@ -3,6 +3,7 @@ wayland_scanner_bin = wayland_scanner.get_pkgconfig_variable('wayland_scanner'
protocols_server = [
wayland_protocols_dir / 'stable/xdg-shell/xdg-shell.xml',
'kiwmi-ipc.xml',
]
protocols_server_src = []
@ -12,14 +13,14 @@ foreach protocol : protocols_server
protocols_server_src += custom_target(
protocol.underscorify() + '_server_c',
input: protocol,
output: '@BASENAME@-protocol.c',
output: '@BASENAME@-server-protocol.c',
command: [wayland_scanner_bin, 'private-code', '@INPUT@', '@OUTPUT@'],
)
protocols_server_inc += custom_target(
protocol.underscorify() + '_server_h',
input: protocol,
output: '@BASENAME@-protocol.h',
output: '@BASENAME@-server-protocol.h',
command: [wayland_scanner_bin, 'server-header', '@INPUT@', '@OUTPUT@'],
)
endforeach
@ -33,3 +34,36 @@ protocols_server = declare_dependency(
link_with: protocols_server_lib,
sources: protocols_server_inc,
)
protocols_client = [
'kiwmi-ipc.xml',
]
protocols_client_src = []
protocols_client_inc = []
foreach protocol : protocols_client
protocols_client_src += custom_target(
protocol.underscorify() + '_client_c',
input: protocol,
output: '@BASENAME@-client-protocol.c',
command: [wayland_scanner_bin, 'private-code', '@INPUT@', '@OUTPUT@'],
)
protocols_client_inc += custom_target(
protocol.underscorify() + '_client_h',
input: protocol,
output: '@BASENAME@-client-protocol.h',
command: [wayland_scanner_bin, 'client-header', '@INPUT@', '@OUTPUT@'],
)
endforeach
protocols_client_lib = static_library(
'protocols_client',
[protocols_client_src, protocols_client_inc],
)
protocols_client = declare_dependency(
link_with: protocols_client_lib,
sources: protocols_client_inc,
)