mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-17 17:26:09 +03:00
cli/gtk: move actual IPC code tp apprt
This commit is contained in:
@ -32,6 +32,7 @@ pub const ColorScheme = structs.ColorScheme;
|
|||||||
pub const CursorPos = structs.CursorPos;
|
pub const CursorPos = structs.CursorPos;
|
||||||
pub const IMEPos = structs.IMEPos;
|
pub const IMEPos = structs.IMEPos;
|
||||||
pub const Selection = structs.Selection;
|
pub const Selection = structs.Selection;
|
||||||
|
pub const OpenNewWindowIPCOptions = structs.OpenNewWindowIPCOptions;
|
||||||
pub const SurfaceSize = structs.SurfaceSize;
|
pub const SurfaceSize = structs.SurfaceSize;
|
||||||
|
|
||||||
/// The implementation to use for the app runtime. This is comptime chosen
|
/// The implementation to use for the app runtime. This is comptime chosen
|
||||||
@ -49,6 +50,7 @@ pub const runtime = switch (build_config.artifact) {
|
|||||||
|
|
||||||
pub const App = runtime.App;
|
pub const App = runtime.App;
|
||||||
pub const Surface = runtime.Surface;
|
pub const Surface = runtime.Surface;
|
||||||
|
pub const IPC = runtime.IPC;
|
||||||
|
|
||||||
/// Runtime is the runtime to use for Ghostty. All runtimes do not provide
|
/// Runtime is the runtime to use for Ghostty. All runtimes do not provide
|
||||||
/// equivalent feature sets.
|
/// equivalent feature sets.
|
||||||
|
@ -1153,6 +1153,9 @@ pub const Inspector = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Functions for inter-process communication.
|
||||||
|
pub const IPC = struct {};
|
||||||
|
|
||||||
// C API
|
// C API
|
||||||
pub const CAPI = struct {
|
pub const CAPI = struct {
|
||||||
const global = &@import("../global.zig").state;
|
const global = &@import("../global.zig").state;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
pub const App = @import("gtk/App.zig");
|
pub const App = @import("gtk/App.zig");
|
||||||
pub const Surface = @import("gtk/Surface.zig");
|
pub const Surface = @import("gtk/Surface.zig");
|
||||||
pub const resourcesDir = @import("gtk/flatpak.zig").resourcesDir;
|
pub const resourcesDir = @import("gtk/flatpak.zig").resourcesDir;
|
||||||
|
pub const IPC = @import("gtk/IPC.zig");
|
||||||
|
|
||||||
test {
|
test {
|
||||||
@import("std").testing.refAllDecls(@This());
|
@import("std").testing.refAllDecls(@This());
|
||||||
|
8
src/apprt/gtk/IPC.zig
Normal file
8
src/apprt/gtk/IPC.zig
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//! Functions for inter-process communication.
|
||||||
|
const IPC = @This();
|
||||||
|
|
||||||
|
pub const openNewWindow = @import("ipc/new_window.zig").openNewWindow;
|
||||||
|
|
||||||
|
test {
|
||||||
|
_ = openNewWindow;
|
||||||
|
}
|
@ -3,7 +3,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
const gio = @import("gio");
|
const gio = @import("gio");
|
||||||
const glib = @import("glib");
|
const glib = @import("glib");
|
||||||
const Options = @import("../new_window.zig").Options;
|
const apprt = @import("../../../apprt.zig");
|
||||||
|
|
||||||
// Use a D-Bus method call to open a new window on GTK.
|
// Use a D-Bus method call to open a new window on GTK.
|
||||||
// See: https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI
|
// See: https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI
|
||||||
@ -17,42 +17,46 @@ const Options = @import("../new_window.zig").Options;
|
|||||||
// `ghostty +new-window --release -e echo hello` would be equivalent to the following command:
|
// `ghostty +new-window --release -e echo hello` would be equivalent to the following command:
|
||||||
//
|
//
|
||||||
// ```
|
// ```
|
||||||
// gdbus call --session --dest con.mitchellh.ghostty --object-path /com/mitchellh/ghostty --method org.gtk.Actions.Activate new-window-command '[<@as ["echo" "hello"]>]' []
|
// gdbus call --session --dest com.mitchellh.ghostty --object-path /com/mitchellh/ghostty --method org.gtk.Actions.Activate new-window-command '[<@as ["echo" "hello"]>]' []
|
||||||
// ```
|
// ```
|
||||||
pub fn new_window(alloc: Allocator, stderr: std.fs.File.Writer, opts: Options) (Allocator.Error || std.posix.WriteError)!u8 {
|
pub fn openNewWindow(alloc: Allocator, stderr: std.fs.File.Writer, opts: apprt.OpenNewWindowIPCOptions) (Allocator.Error || std.posix.WriteError)!u8 {
|
||||||
// Get the appropriate bus name and object path for contacting the
|
// Get the appropriate bus name and object path for contacting the
|
||||||
// Ghostty instance we're interested in.
|
// Ghostty instance we're interested in.
|
||||||
const bus_name: [:0]const u8, const object_path: [:0]const u8 = result: {
|
const bus_name: [:0]const u8, const object_path: [:0]const u8 = result: {
|
||||||
// Force the usage of the class specified on the CLI to determine the
|
switch (opts.instance) {
|
||||||
// bus name and object path.
|
.class => |class| {
|
||||||
if (opts.class) |class| {
|
// Force the usage of the class specified on the CLI to determine the
|
||||||
const object_path = try std.fmt.allocPrintZ(alloc, "/{s}", .{class});
|
// bus name and object path.
|
||||||
|
const object_path = try std.fmt.allocPrintZ(alloc, "/{s}", .{class});
|
||||||
|
|
||||||
std.mem.replaceScalar(u8, object_path, '.', '/');
|
std.mem.replaceScalar(u8, object_path, '.', '/');
|
||||||
std.mem.replaceScalar(u8, object_path, '-', '_');
|
std.mem.replaceScalar(u8, object_path, '-', '_');
|
||||||
|
|
||||||
break :result .{ class, object_path };
|
break :result .{ class, object_path };
|
||||||
}
|
},
|
||||||
// Force the usage of the release bus name and object path.
|
.release => {
|
||||||
if (opts.release) {
|
// Force the usage of the release bus name and object path.
|
||||||
break :result .{ "com.mitchellh.ghostty", "/com/mitchellh/ghostty" };
|
break :result .{ "com.mitchellh.ghostty", "/com/mitchellh/ghostty" };
|
||||||
}
|
},
|
||||||
// Force the usage of the debug bus name and object path.
|
.debug => {
|
||||||
if (opts.debug) {
|
// Force the usage of the debug bus name and object path.
|
||||||
break :result .{ "com.mitchellh.ghostty-debug", "/com/mitchellh/ghostty_debug" };
|
break :result .{ "com.mitchellh.ghostty-debug", "/com/mitchellh/ghostty_debug" };
|
||||||
}
|
},
|
||||||
// If there is a `GHOSTTY_CLASS` environment variable, use that as the basis
|
.detect => {
|
||||||
// for the bus name and object path.
|
// If there is a `GHOSTTY_CLASS` environment variable, use that as the basis
|
||||||
if (std.posix.getenv("GHOSTTY_CLASS")) |class| {
|
// for the bus name and object path.
|
||||||
const object_path = try std.fmt.allocPrintZ(alloc, "/{s}", .{class});
|
if (std.posix.getenv("GHOSTTY_CLASS")) |class| {
|
||||||
|
const object_path = try std.fmt.allocPrintZ(alloc, "/{s}", .{class});
|
||||||
|
|
||||||
std.mem.replaceScalar(u8, object_path, '.', '/');
|
std.mem.replaceScalar(u8, object_path, '.', '/');
|
||||||
std.mem.replaceScalar(u8, object_path, '-', '_');
|
std.mem.replaceScalar(u8, object_path, '-', '_');
|
||||||
|
|
||||||
break :result .{ class, object_path };
|
break :result .{ class, object_path };
|
||||||
|
}
|
||||||
|
// Otherwise fall back to the release bus name and object path.
|
||||||
|
break :result .{ "com.mitchellh.ghostty", "/com/mitchellh/ghostty" };
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// Otherwise fall back to the release bus name and object path.
|
|
||||||
break :result .{ "com.mitchellh.ghostty", "/com/mitchellh/ghostty" };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (gio.Application.idIsValid(bus_name.ptr) == 0) {
|
if (gio.Application.idIsValid(bus_name.ptr) == 0) {
|
||||||
@ -96,7 +100,7 @@ pub fn new_window(alloc: Allocator, stderr: std.fs.File.Writer, opts: Options) (
|
|||||||
errdefer builder.unref();
|
errdefer builder.unref();
|
||||||
|
|
||||||
// action
|
// action
|
||||||
if (opts._arguments.items.len == 0) {
|
if (opts.arguments.len == 0) {
|
||||||
builder.add("s", "new-window");
|
builder.add("s", "new-window");
|
||||||
} else {
|
} else {
|
||||||
builder.add("s", "new-window-command");
|
builder.add("s", "new-window-command");
|
||||||
@ -110,10 +114,11 @@ pub fn new_window(alloc: Allocator, stderr: std.fs.File.Writer, opts: Options) (
|
|||||||
var parameters: glib.VariantBuilder = undefined;
|
var parameters: glib.VariantBuilder = undefined;
|
||||||
parameters.init(av);
|
parameters.init(av);
|
||||||
|
|
||||||
if (opts._arguments.items.len > 0) {
|
if (opts.arguments.len > 0) {
|
||||||
// If `-e` was specified on the command line, he first parameter
|
// If `-e` was specified on the command line, the first
|
||||||
// is an array of strings that contain the arguments that came
|
// parameter is an array of strings that contain the arguments
|
||||||
// afer `-e`, which will be interpreted as a command to run.
|
// that came after `-e`, which will be interpreted as a command
|
||||||
|
// to run.
|
||||||
{
|
{
|
||||||
const as = glib.VariantType.new("as");
|
const as = glib.VariantType.new("as");
|
||||||
defer as.free();
|
defer as.free();
|
||||||
@ -121,7 +126,7 @@ pub fn new_window(alloc: Allocator, stderr: std.fs.File.Writer, opts: Options) (
|
|||||||
var command: glib.VariantBuilder = undefined;
|
var command: glib.VariantBuilder = undefined;
|
||||||
command.init(as);
|
command.init(as);
|
||||||
|
|
||||||
for (opts._arguments.items) |argument| {
|
for (opts.arguments) |argument| {
|
||||||
command.add("s", argument.ptr);
|
command.add("s", argument.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +139,7 @@ pub fn new_window(alloc: Allocator, stderr: std.fs.File.Writer, opts: Options) (
|
|||||||
|
|
||||||
{
|
{
|
||||||
const platform_data = glib.VariantType.new("a{sv}");
|
const platform_data = glib.VariantType.new("a{sv}");
|
||||||
defer glib.free(platform_data);
|
defer platform_data.free();
|
||||||
|
|
||||||
builder.open(platform_data);
|
builder.open(platform_data);
|
||||||
defer builder.close();
|
defer builder.close();
|
@ -2,3 +2,5 @@ const internal_os = @import("../os/main.zig");
|
|||||||
pub const resourcesDir = internal_os.resourcesDir;
|
pub const resourcesDir = internal_os.resourcesDir;
|
||||||
pub const App = struct {};
|
pub const App = struct {};
|
||||||
pub const Surface = struct {};
|
pub const Surface = struct {};
|
||||||
|
/// Functions for inter-process communication.
|
||||||
|
pub const IPC = struct {};
|
||||||
|
@ -72,3 +72,23 @@ pub const Selection = struct {
|
|||||||
offset_start: u32,
|
offset_start: u32,
|
||||||
offset_len: u32,
|
offset_len: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const OpenNewWindowIPCOptions = struct {
|
||||||
|
instance: union(enum) {
|
||||||
|
/// Open up a new window in a release instance of Ghostty.
|
||||||
|
release,
|
||||||
|
|
||||||
|
/// Open up a new window in a debug instance of Ghostty.
|
||||||
|
debug,
|
||||||
|
|
||||||
|
/// Open up a new window in a custom instance of Ghostty.
|
||||||
|
class: [:0]const u8,
|
||||||
|
|
||||||
|
/// Detect which instance to open a new window in.
|
||||||
|
detect,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// If `-e` is found in the arguments, this will contain all of the
|
||||||
|
/// arguments to pass to Ghostty as the command.
|
||||||
|
arguments: [][:0]const u8,
|
||||||
|
};
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
const build_config = @import("../build_config.zig");
|
|
||||||
const Action = @import("../cli.zig").ghostty.Action;
|
const Action = @import("../cli.zig").ghostty.Action;
|
||||||
|
const apprt = @import("../apprt.zig");
|
||||||
const args = @import("args.zig");
|
const args = @import("args.zig");
|
||||||
const diagnostics = @import("diagnostics.zig");
|
const diagnostics = @import("diagnostics.zig");
|
||||||
const font = @import("../font/main.zig");
|
|
||||||
const configpkg = @import("../config.zig");
|
|
||||||
const Config = configpkg.Config;
|
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
/// This is set by the CLI parser for deinit.
|
/// This is set by the CLI parser for deinit.
|
||||||
@ -65,12 +61,26 @@ pub const Options = struct {
|
|||||||
/// The `new-window` will use native platform IPC to open up a new window in a
|
/// The `new-window` will use native platform IPC to open up a new window in a
|
||||||
/// running instance of Ghostty.
|
/// running instance of Ghostty.
|
||||||
///
|
///
|
||||||
|
/// If none of `--release`, `--debug`, and `--class` flags are not set, the
|
||||||
|
/// `new-window` command will try and find the class of the running Ghostty
|
||||||
|
/// instance in the `GHOSTTY_CLASS` environment variable. If this environment
|
||||||
|
/// variable is not set, a release instance of Ghostty will be opened.
|
||||||
|
///
|
||||||
/// If the `-e` flag is included on the command line, any arguments that follow
|
/// If the `-e` flag is included on the command line, any arguments that follow
|
||||||
/// will be sent to the running Ghostty instance and used as the command to run
|
/// will be sent to the running Ghostty instance and used as the command to run
|
||||||
/// in the new window rather than the default. If `-e` is not specified, Ghostty
|
/// in the new window rather than the default. If `-e` is not specified, Ghostty
|
||||||
/// will use the default command (either specified with `command` in your config
|
/// will use the default command (either specified with `command` in your config
|
||||||
/// or your default shell as configured on your system).
|
/// or your default shell as configured on your system).
|
||||||
///
|
///
|
||||||
|
/// GTK uses an application ID to identify instances of applications. If Ghostty
|
||||||
|
/// is compiled with release optimizations, the default application ID will be
|
||||||
|
/// `com.mitchellh.ghostty`. If Ghostty is compiled with debug optimizations,
|
||||||
|
/// the default application ID will be `com.mitchellh.ghostty-debug`. The
|
||||||
|
/// `class` configuration entry can be used to set up a custom application
|
||||||
|
/// ID. The class name must follow the requirements defined [in the GTK
|
||||||
|
/// documentation](https://docs.gtk.org/gio/type_func.Application.id_is_valid.html)
|
||||||
|
/// or it will be ignored and Ghostty will use the default as defined above.
|
||||||
|
///
|
||||||
/// On GTK, D-Bus activation must be properly configured. Ghostty does not need
|
/// On GTK, D-Bus activation must be properly configured. Ghostty does not need
|
||||||
/// to be running for this to open a new window, making it suitable for binding
|
/// to be running for this to open a new window, making it suitable for binding
|
||||||
/// to keys in your window manager (if other methods for configuring global
|
/// to keys in your window manager (if other methods for configuring global
|
||||||
@ -78,22 +88,6 @@ pub const Options = struct {
|
|||||||
/// of Ghostty if it is not already running. See the Ghostty website for
|
/// of Ghostty if it is not already running. See the Ghostty website for
|
||||||
/// information on properly configuring D-Bus activation.
|
/// information on properly configuring D-Bus activation.
|
||||||
///
|
///
|
||||||
/// GTK uses an application ID to identify instances of applications. If
|
|
||||||
/// Ghostty is compiled with debug optimizations, the application ID will
|
|
||||||
/// be `com.mitchellh.ghostty-debug`. If Ghostty is compiled with release
|
|
||||||
/// optimizations, the application ID will be `com.mitchellh.ghostty`.
|
|
||||||
///
|
|
||||||
/// The `class` configuration entry can be used to set up a custom application
|
|
||||||
/// ID. The class name must follow the requirements defined [in the GTK
|
|
||||||
/// documentation](https://docs.gtk.org/gio/type_func.Application.id_is_valid.html)
|
|
||||||
/// or it will be ignored and Ghostty will use the default application ID as
|
|
||||||
/// defined above.
|
|
||||||
///
|
|
||||||
/// The `new-window` command will try and find the application ID of the running
|
|
||||||
/// Ghostty instance in the `GHOSTTY_CLASS` environment variable. If this
|
|
||||||
/// environment variable is not set, and any of the command line flags defined
|
|
||||||
/// below are not set, a release instance of Ghostty will be opened.
|
|
||||||
///
|
|
||||||
/// Only supported on GTK.
|
/// Only supported on GTK.
|
||||||
///
|
///
|
||||||
/// Flags:
|
/// Flags:
|
||||||
@ -170,12 +164,23 @@ fn runArgs(alloc_gpa: Allocator, argsIter: anytype) !u8 {
|
|||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
const alloc = arena.allocator();
|
const alloc = arena.allocator();
|
||||||
|
|
||||||
if (comptime build_config.app_runtime == .gtk) {
|
if (@hasDecl(apprt.IPC, "openNewWindow")) {
|
||||||
const new_window = @import("new_window/gtk.zig").new_window;
|
return try apprt.IPC.openNewWindow(
|
||||||
return try new_window(alloc, stderr, opts);
|
alloc,
|
||||||
|
stderr,
|
||||||
|
.{
|
||||||
|
.instance = instance: {
|
||||||
|
if (opts.class) |class| break :instance .{ .class = class };
|
||||||
|
if (opts.release) break :instance .release;
|
||||||
|
if (opts.debug) break :instance .debug;
|
||||||
|
break :instance .detect;
|
||||||
|
},
|
||||||
|
.arguments = opts._arguments.items,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, the platform is unsupported.
|
// If we get here, the platform is not supported.
|
||||||
try stderr.print("+new-window is unsupported on this platform.\n", .{});
|
try stderr.print("+new-window is not supported on this platform.\n", .{});
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user