Add kiwmic IPC
This commit is contained in:
parent
ca69adf365
commit
890602d863
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), Niclas Meyer <niclas@countingsort.com>
|
||||
*
|
||||
* 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 {
|
||||
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
92
kiwmi/luak/ipc.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* Copyright (c), Niclas Meyer <niclas@countingsort.com>
|
||||
*
|
||||
* 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 <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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
103
kiwmic/main.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* Copyright (c), Niclas Meyer <niclas@countingsort.com>
|
||||
*
|
||||
* 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)
|
||||
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
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), Niclas Meyer <niclas@countingsort.com>
|
||||
|
||||
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 = [
|
||||
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,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue