mirror of
https://mzte.de/git/LordMZTE/dotfiles.git
synced 2025-03-04 23:49:59 +01:00
update vinput
This commit is contained in:
parent
34ea3a88d8
commit
95e6283605
5 changed files with 194 additions and 27 deletions
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
148
scripts/vinput/src/clipboard.zig
Normal file
148
scripts/vinput/src/clipboard.zig
Normal 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 => {},
|
||||
}
|
||||
}
|
||||
}
|
22
scripts/vinput/src/ffi.zig
Normal file
22
scripts/vinput/src/ffi.zig
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue