mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-02-05 20:46:27 +01:00
Merged crates, more work on api
This commit is contained in:
parent
da783fcf7f
commit
1a7b98a666
88 changed files with 352 additions and 310 deletions
40
Cargo.toml
40
Cargo.toml
|
@ -1,5 +1,37 @@
|
||||||
[workspace]
|
[package]
|
||||||
members = [
|
name = "pinnacle"
|
||||||
"pinnacle",
|
version = "0.1.0"
|
||||||
"pinnacle_api",
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tracing = "0.1.37"
|
||||||
|
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||||
|
smithay = { git = "https://github.com/Smithay/smithay", rev = "9b3d173" }
|
||||||
|
smithay-drm-extras = { git = "https://github.com/Smithay/smithay", optional = true }
|
||||||
|
thiserror = "1.0.40"
|
||||||
|
xcursor = {version = "0.3.4", optional = true }
|
||||||
|
image = {version = "0.24.0", default-features = false, optional = true}
|
||||||
|
serde = { version = "1.0.164", features = ["derive"] }
|
||||||
|
rmp = { version = "0.8.11" }
|
||||||
|
rmp-serde = { version = "1.1.1" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["egl", "winit", "udev"]
|
||||||
|
egl = ["smithay/use_system_lib", "smithay/backend_egl"]
|
||||||
|
udev = [
|
||||||
|
"smithay-drm-extras",
|
||||||
|
"smithay/backend_libinput",
|
||||||
|
"smithay/backend_udev",
|
||||||
|
"smithay/backend_drm",
|
||||||
|
"smithay/backend_gbm",
|
||||||
|
"smithay/backend_vulkan",
|
||||||
|
"smithay/backend_egl",
|
||||||
|
"smithay/backend_session_libseat",
|
||||||
|
"image",
|
||||||
|
"smithay/renderer_gl",
|
||||||
|
"smithay/renderer_multi",
|
||||||
|
"xcursor",
|
||||||
]
|
]
|
||||||
|
winit = ["smithay/backend_winit", "smithay/backend_drm"]
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "pinnacle"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
pinnacle_api = { path = "../pinnacle_api" }
|
|
||||||
tracing = "0.1.37"
|
|
||||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
|
||||||
smithay = { git = "https://github.com/Smithay/smithay", rev = "9b3d173" }
|
|
||||||
smithay-drm-extras = { git = "https://github.com/Smithay/smithay", optional = true }
|
|
||||||
thiserror = "1.0.40"
|
|
||||||
xcursor = {version = "0.3.4", optional = true }
|
|
||||||
image = {version = "0.24.0", default-features = false, optional = true}
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["egl", "winit", "udev"]
|
|
||||||
egl = ["smithay/use_system_lib", "smithay/backend_egl"]
|
|
||||||
udev = [
|
|
||||||
"smithay-drm-extras",
|
|
||||||
"smithay/backend_libinput",
|
|
||||||
"smithay/backend_udev",
|
|
||||||
"smithay/backend_drm",
|
|
||||||
"smithay/backend_gbm",
|
|
||||||
"smithay/backend_vulkan",
|
|
||||||
"smithay/backend_egl",
|
|
||||||
"smithay/backend_session_libseat",
|
|
||||||
"image",
|
|
||||||
"smithay/renderer_gl",
|
|
||||||
"smithay/renderer_multi",
|
|
||||||
"xcursor",
|
|
||||||
]
|
|
||||||
winit = ["smithay/backend_winit", "smithay/backend_drm"]
|
|
|
@ -1,15 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "pinnacle_api"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
tracing = "0.1.37"
|
|
||||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
|
||||||
rkyv = { version = "0.7.42", features = ["validation", "strict"] }
|
|
||||||
num_enum = "0.6.1"
|
|
||||||
serde = { version = "1.0.164", features = ["derive"] }
|
|
||||||
serde_json = { version = "1.0.96" }
|
|
||||||
rmp-serde = { version = "1.1.1" }
|
|
||||||
xkbcommon = { version = "0.5.0" }
|
|
||||||
smithay = { git = "https://github.com/Smithay/smithay", rev = "9b3d173" }
|
|
|
@ -1,189 +0,0 @@
|
||||||
use std::{
|
|
||||||
error::Error,
|
|
||||||
io,
|
|
||||||
os::unix::net::{UnixListener, UnixStream},
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
|
|
||||||
use smithay::reexports::calloop::{
|
|
||||||
self, generic::Generic, EventSource, Interest, Mode, PostAction,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::message::Msg;
|
|
||||||
|
|
||||||
pub mod message;
|
|
||||||
|
|
||||||
const SOCKET_PATH: &str = "/tmp/pinnacle_socket";
|
|
||||||
|
|
||||||
pub fn run() -> Result<(), Box<dyn Error>> {
|
|
||||||
let socket_path = Path::new(SOCKET_PATH);
|
|
||||||
|
|
||||||
if socket_path.exists() {
|
|
||||||
std::fs::remove_file(socket_path)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let listener = UnixListener::bind(SOCKET_PATH)?;
|
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
for stream in listener.incoming() {
|
|
||||||
match stream {
|
|
||||||
Ok(stream) => {
|
|
||||||
std::thread::spawn(|| handle_client(stream));
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
eprintln!("Incoming stream error: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_client(stream: UnixStream) {
|
|
||||||
loop {
|
|
||||||
let msg: Msg = rmp_serde::from_read(&stream).unwrap();
|
|
||||||
|
|
||||||
println!("{:?}", msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PinnacleSocketSource {
|
|
||||||
socket: Generic<UnixListener>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PinnacleSocketSource {
|
|
||||||
pub fn new() -> Result<Self, io::Error> {
|
|
||||||
let socket_path = Path::new(SOCKET_PATH);
|
|
||||||
|
|
||||||
if socket_path.exists() {
|
|
||||||
std::fs::remove_file(socket_path)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let listener = UnixListener::bind(SOCKET_PATH)?;
|
|
||||||
|
|
||||||
let socket = Generic::new(listener, Interest::READ, Mode::Level);
|
|
||||||
|
|
||||||
Ok(Self { socket })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventSource for PinnacleSocketSource {
|
|
||||||
type Event = UnixStream;
|
|
||||||
|
|
||||||
type Metadata = ();
|
|
||||||
|
|
||||||
type Ret = ();
|
|
||||||
|
|
||||||
type Error = io::Error;
|
|
||||||
|
|
||||||
fn process_events<F>(
|
|
||||||
&mut self,
|
|
||||||
readiness: calloop::Readiness,
|
|
||||||
token: calloop::Token,
|
|
||||||
mut callback: F,
|
|
||||||
) -> Result<calloop::PostAction, Self::Error>
|
|
||||||
where
|
|
||||||
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
|
|
||||||
{
|
|
||||||
self.socket
|
|
||||||
.process_events(readiness, token, |_readiness, listener| {
|
|
||||||
listener.set_nonblocking(true)?;
|
|
||||||
while let Ok((stream, _sock_addr)) = listener.accept() {
|
|
||||||
stream.set_nonblocking(true)?;
|
|
||||||
callback(stream, &mut ());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(PostAction::Continue)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register(
|
|
||||||
&mut self,
|
|
||||||
poll: &mut calloop::Poll,
|
|
||||||
token_factory: &mut calloop::TokenFactory,
|
|
||||||
) -> calloop::Result<()> {
|
|
||||||
self.socket.register(poll, token_factory)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reregister(
|
|
||||||
&mut self,
|
|
||||||
poll: &mut calloop::Poll,
|
|
||||||
token_factory: &mut calloop::TokenFactory,
|
|
||||||
) -> calloop::Result<()> {
|
|
||||||
self.socket.reregister(poll, token_factory)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unregister(&mut self, poll: &mut calloop::Poll) -> calloop::Result<()> {
|
|
||||||
self.socket.unregister(poll)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PinnacleStreamSource {
|
|
||||||
stream: Generic<UnixStream>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PinnacleStreamSource {
|
|
||||||
pub fn new(stream: UnixStream) -> Self {
|
|
||||||
Self {
|
|
||||||
stream: Generic::new(stream, Interest::READ, Mode::Level),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventSource for PinnacleStreamSource {
|
|
||||||
type Event = Msg;
|
|
||||||
|
|
||||||
type Metadata = ();
|
|
||||||
|
|
||||||
type Ret = ();
|
|
||||||
|
|
||||||
type Error = io::Error;
|
|
||||||
|
|
||||||
fn process_events<F>(
|
|
||||||
&mut self,
|
|
||||||
readiness: calloop::Readiness,
|
|
||||||
token: calloop::Token,
|
|
||||||
mut callback: F,
|
|
||||||
) -> Result<PostAction, Self::Error>
|
|
||||||
where
|
|
||||||
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
|
|
||||||
{
|
|
||||||
self.stream
|
|
||||||
.process_events(readiness, token, |_readiness, stream| {
|
|
||||||
match rmp_serde::from_read(stream as &UnixStream) {
|
|
||||||
Ok(msg) => callback(msg, &mut ()),
|
|
||||||
Err(rmp_serde::decode::Error::InvalidMarkerRead(err))
|
|
||||||
if err.kind() == io::ErrorKind::UnexpectedEof =>
|
|
||||||
{
|
|
||||||
stream.shutdown(std::net::Shutdown::Both)?;
|
|
||||||
println!("Stream closed: {:?}", err);
|
|
||||||
return Ok(PostAction::Remove);
|
|
||||||
}
|
|
||||||
Err(err) => println!("{:?}", err),
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(PostAction::Continue)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register(
|
|
||||||
&mut self,
|
|
||||||
poll: &mut calloop::Poll,
|
|
||||||
token_factory: &mut calloop::TokenFactory,
|
|
||||||
) -> calloop::Result<()> {
|
|
||||||
self.stream.register(poll, token_factory)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reregister(
|
|
||||||
&mut self,
|
|
||||||
poll: &mut calloop::Poll,
|
|
||||||
token_factory: &mut calloop::TokenFactory,
|
|
||||||
) -> calloop::Result<()> {
|
|
||||||
self.stream.reregister(poll, token_factory)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unregister(&mut self, poll: &mut calloop::Poll) -> calloop::Result<()> {
|
|
||||||
self.stream.unregister(poll)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +1,2 @@
|
||||||
The cffi library courtesy of https://github.com/q66/cffi-lua.
|
|
||||||
The luaposix library courtesy of https://github.com/luaposix/luaposix.
|
The luaposix library courtesy of https://github.com/luaposix/luaposix.
|
||||||
|
NOTE: there is an issue with this library where recv's return value is size_t, not ssize_t as it should be. This library uses a patched version, see https://github.com/luaposix/luaposix/issues/354.
|
||||||
|
|
|
@ -1,29 +1,35 @@
|
||||||
-- require("luarocks.loader")
|
-- require("luarocks.loader")
|
||||||
|
|
||||||
package.path = "./lib/?.lua;./lib/?/init.lua;" .. package.path
|
local LOCAL_PATH = "/home/jason/projects/pinnacle/pinnacle_api_lua"
|
||||||
package.cpath = "./lib/?.so;" .. package.cpath
|
|
||||||
|
package.path = LOCAL_PATH .. "/lib/?.lua;" .. LOCAL_PATH .. "/lib/?/init.lua;" .. package.path
|
||||||
|
package.cpath = LOCAL_PATH .. "/lib/?.so;" .. package.cpath
|
||||||
|
|
||||||
local socket = require("posix.sys.socket")
|
local socket = require("posix.sys.socket")
|
||||||
local msgpack = require("lib.msgpack")
|
local fcntl = require("posix.fcntl")
|
||||||
|
local msgpack = require("msgpack")
|
||||||
|
|
||||||
local SOCKET_PATH = "/tmp/pinnacle_socket"
|
local SOCKET_PATH = "/tmp/pinnacle_socket"
|
||||||
|
|
||||||
local CONFIG_PATH = os.getenv("XDG_CONFIG_HOME") .. "/pinnacle/init.lua"
|
local CONFIG_PATH = (os.getenv("XDG_CONFIG_HOME") or "~/.config") .. "/pinnacle/init.lua"
|
||||||
|
|
||||||
package.path = CONFIG_PATH .. ";" .. package.path
|
package.path = CONFIG_PATH .. ";" .. package.path
|
||||||
|
|
||||||
local sockaddr = {
|
---@type integer
|
||||||
family = socket.AF_UNIX,
|
|
||||||
path = SOCKET_PATH,
|
|
||||||
}
|
|
||||||
|
|
||||||
local socket_fd = assert(socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0), "Failed to create socket")
|
local socket_fd = assert(socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0), "Failed to create socket")
|
||||||
print("created socket at fd " .. socket_fd)
|
print("created socket at fd " .. socket_fd)
|
||||||
|
|
||||||
assert(0 == socket.connect(socket_fd, sockaddr), "Failed to connect to Pinnacle socket")
|
assert(0 == socket.connect(socket_fd, {
|
||||||
|
family = socket.AF_UNIX,
|
||||||
|
path = SOCKET_PATH,
|
||||||
|
}), "Failed to connect to Pinnacle socket")
|
||||||
|
|
||||||
function SendMsg(data)
|
function SendMsg(data)
|
||||||
socket.send(socket_fd, msgpack.encode(data))
|
local encoded = msgpack.encode(data)
|
||||||
|
assert(encoded)
|
||||||
|
local len = encoded:len()
|
||||||
|
socket.send(socket_fd, string.pack("=I4", len))
|
||||||
|
socket.send(socket_fd, encoded)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type function[]
|
---@type function[]
|
||||||
|
@ -31,24 +37,51 @@ CallbackTable = {}
|
||||||
|
|
||||||
assert(pcall(require, "pinnacle"), "config file not found")
|
assert(pcall(require, "pinnacle"), "config file not found")
|
||||||
|
|
||||||
-- local str = msgpack.encode({
|
---Read the specified number of bytes.
|
||||||
-- SetMousebind = { button = 6 },
|
---@param socket_fd integer The socket file descriptor
|
||||||
-- })
|
---@param count integer The amount of bytes to read
|
||||||
-- local str = msgpack.encode({
|
---@return string|nil data
|
||||||
-- SetKeybind = {
|
---@return string|nil err_msg
|
||||||
-- key = "This is a key",
|
---@return integer|nil err_num
|
||||||
-- modifiers = { "ctrl", "boogers", "numpty" },
|
local function read_exact(socket_fd, count)
|
||||||
-- },
|
local len_to_read = count
|
||||||
-- })
|
local data = ""
|
||||||
-- print(str)
|
while len_to_read > 0 do
|
||||||
--
|
local bytes, err_msg, errnum = socket.recv(socket_fd, len_to_read)
|
||||||
-- socket.send(socket_fd, str)
|
|
||||||
|
|
||||||
-- unistd.close(socket_fd)
|
if bytes == nil then
|
||||||
|
-- TODO: handle errors
|
||||||
|
print("bytes was nil")
|
||||||
|
return bytes, err_msg, errnum
|
||||||
|
end
|
||||||
|
|
||||||
-- local keys = require("keys")
|
---@type integer
|
||||||
--
|
local recv_len = bytes:len()
|
||||||
-- local input = require("input")
|
|
||||||
-- input.keybind({ "Shift", "Ctrl" }, keys.c, "CloseWindow")
|
if recv_len == 0 then
|
||||||
while true do
|
print("stream closed")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
len_to_read = len_to_read - recv_len
|
||||||
|
assert(len_to_read >= 0, "Overread message boundary")
|
||||||
|
|
||||||
|
data = data .. bytes
|
||||||
|
end
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: set timeouts so that you actually make sure the msg is correct
|
||||||
|
while true do
|
||||||
|
local msg_len_bytes, err_msg, err_num = read_exact(socket_fd, 4)
|
||||||
|
assert(msg_len_bytes)
|
||||||
|
|
||||||
|
---@type integer
|
||||||
|
local msg_len = string.unpack("=I4", msg_len_bytes)
|
||||||
|
|
||||||
|
local msg_bytes, err_msg2, err_num2 = read_exact(socket_fd, msg_len)
|
||||||
|
assert(msg_bytes)
|
||||||
|
|
||||||
|
local tb = msgpack.decode(msg_bytes)
|
||||||
|
print(tb)
|
||||||
end
|
end
|
||||||
|
|
|
@ -346,7 +346,12 @@ return {
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- primary decode function
|
-- Decode a string of MessagePack data into objects.
|
||||||
|
--
|
||||||
|
---@param data string The MessagePack packet
|
||||||
|
---@param position any
|
||||||
|
---@return any ... The decoded values unpacked. If decoding failed, nil
|
||||||
|
---@return string | nil error The string "cannot decode MessagePack" if decoding failed
|
||||||
decode = function(data, position)
|
decode = function(data, position)
|
||||||
local values, value, ok = {}
|
local values, value, ok = {}
|
||||||
position = position or 1
|
position = position or 1
|
||||||
|
|
BIN
pinnacle_api_lua/lib/posix/ctype.so
Executable file
BIN
pinnacle_api_lua/lib/posix/ctype.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/dirent.so
Executable file
BIN
pinnacle_api_lua/lib/posix/dirent.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/errno.so
Executable file
BIN
pinnacle_api_lua/lib/posix/errno.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/fcntl.so
Executable file
BIN
pinnacle_api_lua/lib/posix/fcntl.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/fnmatch.so
Executable file
BIN
pinnacle_api_lua/lib/posix/fnmatch.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/glob.so
Executable file
BIN
pinnacle_api_lua/lib/posix/glob.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/grp.so
Executable file
BIN
pinnacle_api_lua/lib/posix/grp.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/libgen.so
Executable file
BIN
pinnacle_api_lua/lib/posix/libgen.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/poll.so
Executable file
BIN
pinnacle_api_lua/lib/posix/poll.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/pwd.so
Executable file
BIN
pinnacle_api_lua/lib/posix/pwd.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sched.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sched.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/signal.so
Executable file
BIN
pinnacle_api_lua/lib/posix/signal.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/stdio.so
Executable file
BIN
pinnacle_api_lua/lib/posix/stdio.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/stdlib.so
Executable file
BIN
pinnacle_api_lua/lib/posix/stdlib.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/msg.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/msg.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/resource.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/resource.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/socket.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/socket.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/stat.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/stat.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/statvfs.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/statvfs.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/time.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/time.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/times.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/times.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/utsname.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/utsname.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/sys/wait.so
Executable file
BIN
pinnacle_api_lua/lib/posix/sys/wait.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/syslog.so
Executable file
BIN
pinnacle_api_lua/lib/posix/syslog.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/termio.so
Executable file
BIN
pinnacle_api_lua/lib/posix/termio.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/time.so
Executable file
BIN
pinnacle_api_lua/lib/posix/time.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/unistd.so
Executable file
BIN
pinnacle_api_lua/lib/posix/unistd.so
Executable file
Binary file not shown.
BIN
pinnacle_api_lua/lib/posix/utime.so
Executable file
BIN
pinnacle_api_lua/lib/posix/utime.so
Executable file
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
144
src/api.rs
Normal file
144
src/api.rs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
pub mod msg;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
io::{self, Read, Write},
|
||||||
|
os::unix::net::{UnixDatagram, UnixListener, UnixStream},
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
use smithay::reexports::calloop::{
|
||||||
|
self, channel::Sender, generic::Generic, EventSource, Interest, Mode, PostAction,
|
||||||
|
};
|
||||||
|
|
||||||
|
use self::msg::{Msg, OutgoingMsg};
|
||||||
|
|
||||||
|
const SOCKET_PATH: &str = "/tmp/pinnacle_socket";
|
||||||
|
|
||||||
|
fn handle_client(mut stream: UnixStream, sender: Sender<Msg>) {
|
||||||
|
loop {
|
||||||
|
let mut len_marker_bytes = [0u8; 4];
|
||||||
|
if let Err(err) = stream.read_exact(&mut len_marker_bytes) {
|
||||||
|
if err.kind() == io::ErrorKind::UnexpectedEof {
|
||||||
|
tracing::warn!("stream closed: {}", err);
|
||||||
|
stream.shutdown(std::net::Shutdown::Both).unwrap();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let len_marker = u32::from_ne_bytes(len_marker_bytes);
|
||||||
|
let mut msg_bytes = vec![0u8; len_marker as usize];
|
||||||
|
|
||||||
|
if let Err(err) = stream.read_exact(msg_bytes.as_mut_slice()) {
|
||||||
|
if err.kind() == io::ErrorKind::UnexpectedEof {
|
||||||
|
tracing::warn!("stream closed: {}", err);
|
||||||
|
stream.shutdown(std::net::Shutdown::Both).unwrap();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let msg: Msg = rmp_serde::from_slice(msg_bytes.as_slice()).unwrap(); // TODO: handle error
|
||||||
|
|
||||||
|
sender.send(msg).unwrap();
|
||||||
|
}
|
||||||
|
tracing::info!("end of handle_client");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PinnacleSocketSource {
|
||||||
|
socket: Generic<UnixListener>,
|
||||||
|
sender: Sender<Msg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PinnacleSocketSource {
|
||||||
|
pub fn new(sender: Sender<Msg>) -> Result<Self, io::Error> {
|
||||||
|
let socket_path = Path::new(SOCKET_PATH);
|
||||||
|
|
||||||
|
if let Ok(exists) = socket_path.try_exists() {
|
||||||
|
if exists {
|
||||||
|
std::fs::remove_file(socket_path)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let listener = UnixListener::bind(SOCKET_PATH)?;
|
||||||
|
listener.set_nonblocking(true)?;
|
||||||
|
|
||||||
|
let socket = Generic::new(listener, Interest::READ, Mode::Level);
|
||||||
|
|
||||||
|
Ok(Self { socket, sender })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_to_client(
|
||||||
|
stream: &mut UnixStream,
|
||||||
|
msg: &OutgoingMsg,
|
||||||
|
) -> Result<(), rmp_serde::encode::Error> {
|
||||||
|
let msg = rmp_serde::to_vec_named(msg)?;
|
||||||
|
let msg_len = msg.len() as u32;
|
||||||
|
let bytes = msg_len.to_ne_bytes();
|
||||||
|
|
||||||
|
if let Err(err) = stream.write_all(&bytes) {
|
||||||
|
if err.kind() == io::ErrorKind::BrokenPipe {
|
||||||
|
// TODO: notify user that config daemon is ded
|
||||||
|
return Ok(()); // TODO:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Err(err) = stream.write_all(msg.as_slice()) {
|
||||||
|
if err.kind() == io::ErrorKind::BrokenPipe {
|
||||||
|
// TODO: something
|
||||||
|
return Ok(()); // TODO:
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventSource for PinnacleSocketSource {
|
||||||
|
type Event = UnixStream;
|
||||||
|
|
||||||
|
type Metadata = ();
|
||||||
|
|
||||||
|
type Ret = ();
|
||||||
|
|
||||||
|
type Error = io::Error;
|
||||||
|
|
||||||
|
fn process_events<F>(
|
||||||
|
&mut self,
|
||||||
|
readiness: calloop::Readiness,
|
||||||
|
token: calloop::Token,
|
||||||
|
mut callback: F,
|
||||||
|
) -> Result<calloop::PostAction, Self::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
|
||||||
|
{
|
||||||
|
self.socket
|
||||||
|
.process_events(readiness, token, |_readiness, listener| {
|
||||||
|
while let Ok((stream, _sock_addr)) = listener.accept() {
|
||||||
|
let sender = self.sender.clone();
|
||||||
|
let callback_stream = stream.try_clone().unwrap(); // TODO: error
|
||||||
|
callback(callback_stream, &mut ());
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
handle_client(stream, sender);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(PostAction::Continue)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register(
|
||||||
|
&mut self,
|
||||||
|
poll: &mut calloop::Poll,
|
||||||
|
token_factory: &mut calloop::TokenFactory,
|
||||||
|
) -> calloop::Result<()> {
|
||||||
|
self.socket.register(poll, token_factory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reregister(
|
||||||
|
&mut self,
|
||||||
|
poll: &mut calloop::Poll,
|
||||||
|
token_factory: &mut calloop::TokenFactory,
|
||||||
|
) -> calloop::Result<()> {
|
||||||
|
self.socket.reregister(poll, token_factory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unregister(&mut self, poll: &mut calloop::Poll) -> calloop::Result<()> {
|
||||||
|
self.socket.unregister(poll)
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,3 +41,9 @@ impl<T: IntoIterator<Item = Modifiers>> From<T> for ModifierMask {
|
||||||
Self(mask)
|
Self(mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Messages sent from the server to each client.
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub enum OutgoingMsg {
|
||||||
|
CallCallback(u32),
|
||||||
|
}
|
|
@ -138,7 +138,7 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
||||||
Some(dmabuf_default_feedback)
|
Some(dmabuf_default_feedback)
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
tracing::warn!("failed to query render node, dmabuf will use v3"); // TODO: tracing
|
tracing::warn!("failed to query render node, dmabuf will use v3");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -181,6 +181,11 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
||||||
evt_loop_handle,
|
evt_loop_handle,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// std::process::Command::new("lua")
|
||||||
|
// .arg("../pinnacle_api_lua/init.lua")
|
||||||
|
// .spawn()
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
state
|
state
|
||||||
.shm_state
|
.shm_state
|
||||||
.update_formats(state.backend_data.backend.renderer().shm_formats());
|
.update_formats(state.backend_data.backend.renderer().shm_formats());
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use pinnacle_api::message::{ModifierMask, Modifiers};
|
use crate::api::msg::{ModifierMask, Modifiers, OutgoingMsg};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::input::{
|
backend::input::{
|
||||||
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent,
|
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent,
|
||||||
|
@ -216,13 +216,13 @@ impl<B: Backend> State<B> {
|
||||||
.keybinds
|
.keybinds
|
||||||
.get(&(modifier_mask.into(), keysym.modified_sym()))
|
.get(&(modifier_mask.into(), keysym.modified_sym()))
|
||||||
{
|
{
|
||||||
return FilterResult::Intercept(1);
|
return FilterResult::Intercept(*callback_id);
|
||||||
}
|
}
|
||||||
match keysym.modified_sym() {
|
match keysym.modified_sym() {
|
||||||
keysyms::KEY_L => return FilterResult::Intercept(1),
|
keysyms::KEY_L => return FilterResult::Intercept(100),
|
||||||
keysyms::KEY_K => return FilterResult::Intercept(2),
|
keysyms::KEY_K => return FilterResult::Intercept(200),
|
||||||
keysyms::KEY_J => return FilterResult::Intercept(3),
|
keysyms::KEY_J => return FilterResult::Intercept(300),
|
||||||
keysyms::KEY_H => return FilterResult::Intercept(4),
|
keysyms::KEY_H => return FilterResult::Intercept(400),
|
||||||
keysyms::KEY_Escape => {
|
keysyms::KEY_Escape => {
|
||||||
state.loop_signal.stop();
|
state.loop_signal.stop();
|
||||||
return FilterResult::Intercept(0);
|
return FilterResult::Intercept(0);
|
||||||
|
@ -250,11 +250,22 @@ impl<B: Backend> State<B> {
|
||||||
self.move_mode = move_mode;
|
self.move_mode = move_mode;
|
||||||
|
|
||||||
let program = match action {
|
let program = match action {
|
||||||
Some(1) => "alacritty",
|
Some(100) => "alacritty",
|
||||||
Some(2) => "nautilus",
|
Some(200) => "nautilus",
|
||||||
Some(3) => "kitty",
|
Some(300) => "kitty",
|
||||||
Some(4) => "foot",
|
Some(400) => "foot",
|
||||||
Some(_) | None => return,
|
Some(callback_id) => {
|
||||||
|
if let Some(stream) = self.api_state.stream.as_mut() {
|
||||||
|
if let Err(err) =
|
||||||
|
crate::api::send_to_client(stream, &OutgoingMsg::CallCallback(callback_id))
|
||||||
|
{
|
||||||
|
// TODO: print error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
tracing::info!("Spawning {}", program);
|
tracing::info!("Spawning {}", program);
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod api;
|
||||||
mod backend;
|
mod backend;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod grab;
|
mod grab;
|
|
@ -1,6 +1,11 @@
|
||||||
use std::{collections::HashMap, error::Error, os::fd::AsRawFd, sync::Arc};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
error::Error,
|
||||||
|
os::{fd::AsRawFd, unix::net::UnixStream},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use pinnacle_api::{message::Msg, PinnacleSocketSource, PinnacleStreamSource};
|
use crate::api::{msg::Msg, PinnacleSocketSource, PinnacleStreamSource};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::element::RenderElementStates,
|
backend::renderer::element::RenderElementStates,
|
||||||
desktop::{
|
desktop::{
|
||||||
|
@ -13,7 +18,10 @@ use smithay::{
|
||||||
input::{keyboard::XkbConfig, pointer::CursorImageStatus, Seat, SeatState},
|
input::{keyboard::XkbConfig, pointer::CursorImageStatus, Seat, SeatState},
|
||||||
output::Output,
|
output::Output,
|
||||||
reexports::{
|
reexports::{
|
||||||
calloop::{generic::Generic, Interest, LoopHandle, LoopSignal, Mode, PostAction},
|
calloop::{
|
||||||
|
self, channel::Event, generic::Generic, Interest, LoopHandle, LoopSignal, Mode,
|
||||||
|
PostAction,
|
||||||
|
},
|
||||||
wayland_server::{
|
wayland_server::{
|
||||||
backend::{ClientData, ClientId, DisconnectReason},
|
backend::{ClientData, ClientId, DisconnectReason},
|
||||||
protocol::wl_surface::WlSurface,
|
protocol::wl_surface::WlSurface,
|
||||||
|
@ -59,6 +67,7 @@ pub struct State<B: Backend> {
|
||||||
pub viewporter_state: ViewporterState,
|
pub viewporter_state: ViewporterState,
|
||||||
pub fractional_scale_manager_state: FractionalScaleManagerState,
|
pub fractional_scale_manager_state: FractionalScaleManagerState,
|
||||||
pub input_state: InputState,
|
pub input_state: InputState,
|
||||||
|
pub api_state: ApiState,
|
||||||
|
|
||||||
pub popup_manager: PopupManager,
|
pub popup_manager: PopupManager,
|
||||||
|
|
||||||
|
@ -97,29 +106,58 @@ impl<B: Backend> State<B> {
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
loop_handle.insert_source(PinnacleSocketSource::new()?, |stream, _, data| {
|
let (tx_channel, rx_channel) = calloop::channel::channel::<Msg>();
|
||||||
data.state
|
loop_handle.insert_source(rx_channel, |msg, _, data| match msg {
|
||||||
.loop_handle
|
Event::Msg(msg) => {
|
||||||
.insert_source(PinnacleStreamSource::new(stream), |msg, _, data| {
|
match msg {
|
||||||
// TODO: do stuff with msg
|
Msg::SetKeybind {
|
||||||
match msg {
|
key,
|
||||||
Msg::SetKeybind {
|
modifiers,
|
||||||
key,
|
callback_id,
|
||||||
modifiers,
|
} => {
|
||||||
callback_id,
|
tracing::info!("set keybind: {:?}, {}", modifiers, key);
|
||||||
} => {
|
data.state
|
||||||
tracing::info!("set keybind: {:?}, {}", modifiers, key);
|
.input_state
|
||||||
data.state
|
.keybinds
|
||||||
.input_state
|
.insert((modifiers.into(), key), callback_id);
|
||||||
.keybinds
|
}
|
||||||
.insert((modifiers.into(), key), callback_id);
|
Msg::SetMousebind { button } => todo!(),
|
||||||
}
|
};
|
||||||
Msg::SetMousebind { button } => todo!(),
|
}
|
||||||
};
|
Event::Closed => todo!(),
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// std::thread::spawn(move || {
|
||||||
|
// crate::api::init_api_socket(tx_channel).unwrap();
|
||||||
|
// });
|
||||||
|
|
||||||
|
loop_handle.insert_source(PinnacleSocketSource::new(tx_channel)?, |stream, _, data| {
|
||||||
|
if let Some(old_stream) = data.state.api_state.stream.replace(stream) {
|
||||||
|
old_stream.shutdown(std::net::Shutdown::Both).unwrap();
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
// data.state
|
||||||
|
// .loop_handle
|
||||||
|
// .insert_source(PinnacleStreamSource::new(stream), |msg, _, data| {
|
||||||
|
// // TODO: do stuff with msg
|
||||||
|
// match msg {
|
||||||
|
// Msg::SetKeybind {
|
||||||
|
// key,
|
||||||
|
// modifiers,
|
||||||
|
// callback_id,
|
||||||
|
// } => {
|
||||||
|
// tracing::info!("set keybind: {:?}, {}", modifiers, key);
|
||||||
|
// data.state
|
||||||
|
// .input_state
|
||||||
|
// .keybinds
|
||||||
|
// .insert((modifiers.into(), key), callback_id);
|
||||||
|
// }
|
||||||
|
// Msg::SetMousebind { button } => todo!(),
|
||||||
|
// };
|
||||||
|
// })
|
||||||
|
// .unwrap();
|
||||||
|
// })?;
|
||||||
|
|
||||||
let display_handle = display.handle();
|
let display_handle = display.handle();
|
||||||
let mut seat_state = SeatState::new();
|
let mut seat_state = SeatState::new();
|
||||||
let mut seat = seat_state.new_wl_seat(&display_handle, backend_data.seat_name());
|
let mut seat = seat_state.new_wl_seat(&display_handle, backend_data.seat_name());
|
||||||
|
@ -147,6 +185,7 @@ impl<B: Backend> State<B> {
|
||||||
input_state: InputState {
|
input_state: InputState {
|
||||||
keybinds: HashMap::new(),
|
keybinds: HashMap::new(),
|
||||||
},
|
},
|
||||||
|
api_state: ApiState { stream: None },
|
||||||
|
|
||||||
seat,
|
seat,
|
||||||
|
|
||||||
|
@ -165,6 +204,7 @@ impl<B: Backend> State<B> {
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
pub fn handle_msg(msg: Msg) {
|
pub fn handle_msg(msg: Msg) {
|
||||||
match msg {
|
match msg {
|
||||||
Msg::SetKeybind {
|
Msg::SetKeybind {
|
||||||
|
@ -231,3 +271,7 @@ pub fn take_presentation_feedback(
|
||||||
|
|
||||||
output_presentation_feedback
|
output_presentation_feedback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ApiState {
|
||||||
|
pub stream: Option<UnixStream>,
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue