update vinput

This commit is contained in:
LordMZTE 2022-10-17 10:47:36 +02:00
parent 34ea3a88d8
commit 95e6283605
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
5 changed files with 194 additions and 27 deletions

View file

@ -1,5 +1,5 @@
require("nvim-tree").setup {
open_on_setup = true,
open_on_setup = not vim.g.started_by_vinput,
open_on_setup_file = false,
diagnostics = {
enable = true,

View file

@ -14,6 +14,10 @@ pub fn build(b: *std.build.Builder) void {
const exe = b.addExecutable("vinput", "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.linkLibC();
exe.linkSystemLibrary("x11");
exe.install();
const run_cmd = exe.run();

View file

@ -0,0 +1,148 @@
const std = @import("std");
const ffi = @import("ffi.zig");
const c = ffi.c;
const log = std.log.scoped(.clipboard);
/// Provides the given data to the X clipboard ONCE
pub fn provideClipboard(data: []const u8, alloc: std.mem.Allocator) !void {
_ = alloc;
const dpy = c.XOpenDisplay(
c.getenv("DISPLAY") orelse return error.DisplayNotSet,
) orelse return error.OpenDisplay;
defer _ = c.XCloseDisplay(dpy);
const screen_n = c.XDefaultScreen(dpy);
const screen = c.XScreenOfDisplay(dpy, screen_n);
const win = c.XCreateSimpleWindow(
dpy,
screen.*.root,
0,
0,
1,
1,
0,
screen.*.black_pixel,
screen.*.white_pixel,
);
const selection = c.XInternAtom(dpy, "CLIPBOARD", 0);
const targets_atom = c.XInternAtom(dpy, "TARGETS", 0);
const text_atom = c.XInternAtom(dpy, "TEXT", 0);
var utf8_atom = c.XInternAtom(dpy, "UTF8_STRING", 1);
if (utf8_atom == c.None) {
utf8_atom = c.XA_STRING;
}
_ = c.XSetSelectionOwner(dpy, selection, win, 0);
if (c.XGetSelectionOwner(dpy, selection) != win) {
return error.FailedToAquireSelection;
}
log.info("providing clipboard", .{});
var event: c.XEvent = undefined;
while (true) {
try ffi.checkXError(dpy, c.XNextEvent(dpy, &event));
switch (event.type) {
c.SelectionRequest => {
if (event.xselectionrequest.selection != selection)
continue;
const xsr = event.xselectionrequest;
var sent_data = false;
var r: c_int = 0;
if (xsr.target == targets_atom) {
r = c.XChangeProperty(
xsr.display,
xsr.requestor,
xsr.property,
c.XA_ATOM,
32,
c.PropModeReplace,
@ptrCast([*c]u8, &utf8_atom),
1,
);
} else if (xsr.target == c.XA_STRING or xsr.target == text_atom) {
r = c.XChangeProperty(
xsr.display,
xsr.requestor,
xsr.property,
c.XA_STRING,
8,
c.PropModeReplace,
data.ptr,
@intCast(c_int, data.len),
);
sent_data = true;
} else if (xsr.target == utf8_atom) {
r = c.XChangeProperty(
xsr.display,
xsr.requestor,
xsr.property,
utf8_atom,
8,
c.PropModeReplace,
data.ptr,
@intCast(c_int, data.len),
);
sent_data = true;
}
if ((r & 2) == 0) {
var ev = c.XSelectionEvent{
.type = c.SelectionNotify,
.display = xsr.display,
.requestor = xsr.requestor,
.selection = xsr.selection,
.time = xsr.time,
.target = xsr.target,
.property = xsr.property,
.serial = 0,
.send_event = 0,
};
_ = c.XSendEvent(dpy, ev.requestor, 0, 0, @ptrCast(*c.XEvent, &ev));
if (sent_data) {
var real: c.Atom = undefined;
var format: c_int = 0;
var n: c_ulong = 0;
var extra: c_ulong = 0;
var name_cstr: [*c]u8 = undefined;
_ = c.XGetWindowProperty(
dpy,
xsr.requestor,
c.XA_WM_NAME,
0,
~@as(c_int, 0),
0,
c.AnyPropertyType,
&real,
&format,
&n,
&extra,
&name_cstr,
);
if (name_cstr != null) {
defer _ = c.XFree(name_cstr);
const name = std.mem.span(name_cstr);
log.info("sent clipboard to {s}", .{name});
} else {
log.info("sent clipboard to unknown window", .{});
}
break;
}
}
},
c.SelectionClear => {
log.info("Selection cleared", .{});
break;
},
else => {},
}
}
}

View file

@ -0,0 +1,22 @@
const std = @import("std");
const log = std.log.scoped(.ffi);
pub const c = @cImport({
@cInclude("stdlib.h");
@cInclude("X11/Xlib.h");
@cInclude("X11/Xatom.h");
});
pub fn checkXError(dpy: *c.Display, code: c_int) !void {
if (code == 0)
return;
var buf: [512]u8 = undefined;
if (c.XGetErrorText(dpy, code, &buf, buf.len) != 0) {
return error.FailedToGetErrorText;
}
log.err("X: {s}", .{buf});
return error.XError;
}

View file

@ -1,4 +1,5 @@
const std = @import("std");
const clipboard = @import("clipboard.zig");
pub const log_level = .debug;
@ -15,17 +16,28 @@ pub fn main() !void {
);
defer alloc.free(filename);
const nvide_argv = [_][]const u8{
"neovide",
"--nofork",
"--x11-wm-class",
//const editor_argv = [_][]const u8{
// "neovide",
// "--nofork",
// "--x11-wm-class",
// "vinput-neovide",
// filename,
//};
const editor_argv = [_][]const u8{
"alacritty",
"--class",
"vinput-neovide",
"-e",
"nvim",
"--cmd",
"let g:started_by_vinput=v:true",
filename,
};
std.log.info("invoking neovide with command {s}", .{&nvide_argv});
std.log.info("invoking editor with command {s}", .{&editor_argv});
var nvide_child = std.ChildProcess.init(&nvide_argv, alloc);
var nvide_child = std.ChildProcess.init(&editor_argv, alloc);
_ = try nvide_child.spawnAndWait();
const stat = std.fs.cwd().statFile(filename) catch |e| {
@ -41,24 +53,6 @@ pub fn main() !void {
var tempfile = try std.fs.openFileAbsolute(filename, .{});
defer tempfile.close();
const xclip_argv = [_][]const u8{
"xclip",
"-sel",
"clip",
};
std.log.info("invoking xclip with command {s}", .{&xclip_argv});
var xclip_child = std.ChildProcess.init(&xclip_argv, alloc);
xclip_child.stdin_behavior = .Pipe;
try xclip_child.spawn();
defer _ = xclip_child.wait() catch {};
if (xclip_child.stdin == null) {
return error.XclipNullStdin;
}
defer xclip_child.stdin = null;
defer xclip_child.stdin.?.close();
std.log.info("mmapping tempfile", .{});
// ooooh memmap, performance!
@ -72,8 +66,7 @@ pub fn main() !void {
);
defer std.os.munmap(fcontent);
std.log.info("writing trimmed tempfile to xclip stdin", .{});
try xclip_child.stdin.?.writeAll(std.mem.trim(u8, fcontent, " \n\r"));
try clipboard.provideClipboard(std.mem.trim(u8, fcontent, " \n\r"), alloc);
}
std.log.info("deleting tempfile {s}", .{filename});
try std.fs.deleteFileAbsolute(filename);