Add kiwmic IPC
This commit is contained in:
parent
cbe587b8c2
commit
b79aa962d6
10 changed files with 313 additions and 2 deletions
18
include/luak/ipc.h
Normal file
18
include/luak/ipc.h
Normal 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 */
|
|
@ -17,6 +17,7 @@
|
||||||
struct kiwmi_lua {
|
struct kiwmi_lua {
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
struct wl_list callbacks; // lua_callback::link
|
struct wl_list callbacks; // lua_callback::link
|
||||||
|
struct wl_global *global;
|
||||||
};
|
};
|
||||||
|
|
||||||
int luaK_callback_register_dispatch(lua_State *L);
|
int luaK_callback_register_dispatch(lua_State *L);
|
||||||
|
|
92
kiwmi/luak/ipc.c
Normal file
92
kiwmi/luak/ipc.c
Normal 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;
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
|
||||||
|
#include "luak/ipc.h"
|
||||||
#include "luak/kiwmi_lua_callback.h"
|
#include "luak/kiwmi_lua_callback.h"
|
||||||
#include "luak/kiwmi_server.h"
|
#include "luak/kiwmi_server.h"
|
||||||
#include "luak/kiwmi_view.h"
|
#include "luak/kiwmi_view.h"
|
||||||
|
@ -54,6 +55,7 @@ luaK_create(struct kiwmi_server *server)
|
||||||
|
|
||||||
lua_State *L = luaL_newstate();
|
lua_State *L = luaL_newstate();
|
||||||
if (!L) {
|
if (!L) {
|
||||||
|
free(lua);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +73,8 @@ luaK_create(struct kiwmi_server *server)
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
||||||
|
lua_close(L);
|
||||||
|
free(lua);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +83,8 @@ luaK_create(struct kiwmi_server *server)
|
||||||
lua_pushlightuserdata(L, server);
|
lua_pushlightuserdata(L, server);
|
||||||
if (lua_pcall(L, 1, 1, 0)) {
|
if (lua_pcall(L, 1, 1, 0)) {
|
||||||
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
||||||
|
lua_close(L);
|
||||||
|
free(lua);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
lua_setglobal(L, "kiwmi");
|
lua_setglobal(L, "kiwmi");
|
||||||
|
@ -87,6 +93,13 @@ luaK_create(struct kiwmi_server *server)
|
||||||
|
|
||||||
wl_list_init(&lua->callbacks);
|
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;
|
return lua;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ kiwmi_sources = files(
|
||||||
'input/cursor.c',
|
'input/cursor.c',
|
||||||
'input/input.c',
|
'input/input.c',
|
||||||
'input/keyboard.c',
|
'input/keyboard.c',
|
||||||
|
'luak/ipc.c',
|
||||||
'luak/kiwmi_lua_callback.c',
|
'luak/kiwmi_lua_callback.c',
|
||||||
'luak/kiwmi_server.c',
|
'luak/kiwmi_server.c',
|
||||||
'luak/kiwmi_view.c',
|
'luak/kiwmi_view.c',
|
||||||
|
|
103
kiwmic/main.c
Normal file
103
kiwmic/main.c
Normal 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, ®istry_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
16
kiwmic/meson.build
Normal 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,
|
||||||
|
)
|
|
@ -18,6 +18,7 @@ add_project_arguments(
|
||||||
|
|
||||||
git = find_program('git', required: false)
|
git = find_program('git', required: false)
|
||||||
lua = dependency('lua')
|
lua = dependency('lua')
|
||||||
|
wayland_client = dependency('wayland-client')
|
||||||
wayland_protocols = dependency('wayland-protocols')
|
wayland_protocols = dependency('wayland-protocols')
|
||||||
wayland_scanner = dependency('wayland-scanner')
|
wayland_scanner = dependency('wayland-scanner')
|
||||||
wayland_server = dependency('wayland-server')
|
wayland_server = dependency('wayland-server')
|
||||||
|
@ -49,3 +50,4 @@ endif
|
||||||
|
|
||||||
subdir('protocols')
|
subdir('protocols')
|
||||||
subdir('kiwmi')
|
subdir('kiwmi')
|
||||||
|
subdir('kiwmic')
|
||||||
|
|
31
protocols/kiwmi-ipc.xml
Normal file
31
protocols/kiwmi-ipc.xml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="kiwmi_ipc">
|
||||||
|
<copyright>
|
||||||
|
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/.
|
||||||
|
</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>
|
|
@ -3,6 +3,7 @@ wayland_scanner_bin = wayland_scanner.get_pkgconfig_variable('wayland_scanner'
|
||||||
|
|
||||||
protocols_server = [
|
protocols_server = [
|
||||||
wayland_protocols_dir / 'stable/xdg-shell/xdg-shell.xml',
|
wayland_protocols_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||||
|
'kiwmi-ipc.xml',
|
||||||
]
|
]
|
||||||
|
|
||||||
protocols_server_src = []
|
protocols_server_src = []
|
||||||
|
@ -12,14 +13,14 @@ foreach protocol : protocols_server
|
||||||
protocols_server_src += custom_target(
|
protocols_server_src += custom_target(
|
||||||
protocol.underscorify() + '_server_c',
|
protocol.underscorify() + '_server_c',
|
||||||
input: protocol,
|
input: protocol,
|
||||||
output: '@BASENAME@-protocol.c',
|
output: '@BASENAME@-server-protocol.c',
|
||||||
command: [wayland_scanner_bin, 'private-code', '@INPUT@', '@OUTPUT@'],
|
command: [wayland_scanner_bin, 'private-code', '@INPUT@', '@OUTPUT@'],
|
||||||
)
|
)
|
||||||
|
|
||||||
protocols_server_inc += custom_target(
|
protocols_server_inc += custom_target(
|
||||||
protocol.underscorify() + '_server_h',
|
protocol.underscorify() + '_server_h',
|
||||||
input: protocol,
|
input: protocol,
|
||||||
output: '@BASENAME@-protocol.h',
|
output: '@BASENAME@-server-protocol.h',
|
||||||
command: [wayland_scanner_bin, 'server-header', '@INPUT@', '@OUTPUT@'],
|
command: [wayland_scanner_bin, 'server-header', '@INPUT@', '@OUTPUT@'],
|
||||||
)
|
)
|
||||||
endforeach
|
endforeach
|
||||||
|
@ -33,3 +34,36 @@ protocols_server = declare_dependency(
|
||||||
link_with: protocols_server_lib,
|
link_with: protocols_server_lib,
|
||||||
sources: protocols_server_inc,
|
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,
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue