mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
Merge pull request #816 from Raiden1411/feat/options
feat: add support for `--fullscreen`, `--title` and `--class` values
This commit is contained in:
@ -67,6 +67,11 @@ class TerminalManager {
|
||||
Self.lastCascadePoint = window.cascadeTopLeft(from: Self.lastCascadePoint)
|
||||
}
|
||||
|
||||
if (ghostty.windowFullscreen) {
|
||||
// NOTE: this doesn't properly handle non-native fullscreen yet
|
||||
c.window?.toggleFullScreen(nil)
|
||||
}
|
||||
|
||||
c.showWindow(self)
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,15 @@ extension Ghostty {
|
||||
return v
|
||||
}
|
||||
|
||||
/// Whether to open new windows in fullscreen.
|
||||
var windowFullscreen: Bool {
|
||||
guard let config = self.config else { return true }
|
||||
var v = false
|
||||
let key = "fullscreen"
|
||||
_ = ghostty_config_get(config, &v, key, UInt(key.count))
|
||||
return v
|
||||
}
|
||||
|
||||
/// The background opacity.
|
||||
var backgroundOpacity: Double {
|
||||
guard let config = self.config else { return 1 }
|
||||
|
@ -155,6 +155,7 @@ const DerivedConfig = struct {
|
||||
window_padding_x: u32,
|
||||
window_padding_y: u32,
|
||||
window_padding_balance: bool,
|
||||
title: ?[:0]const u8,
|
||||
|
||||
pub fn init(alloc_gpa: Allocator, config: *const configpkg.Config) !DerivedConfig {
|
||||
var arena = ArenaAllocator.init(alloc_gpa);
|
||||
@ -180,6 +181,7 @@ const DerivedConfig = struct {
|
||||
.window_padding_x = config.@"window-padding-x",
|
||||
.window_padding_y = config.@"window-padding-y",
|
||||
.window_padding_balance = config.@"window-padding-balance",
|
||||
.title = config.title,
|
||||
|
||||
// Assignments happen sequentially so we have to do this last
|
||||
// so that the memory is captured from allocs above.
|
||||
@ -544,6 +546,8 @@ pub fn init(
|
||||
log.warn("unable to set initial window size: {s}", .{err});
|
||||
};
|
||||
}
|
||||
|
||||
if (config.title) |title| try rt_surface.setTitle(title);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Surface) void {
|
||||
@ -663,6 +667,12 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
|
||||
.change_config => |config| try self.changeConfig(config),
|
||||
|
||||
.set_title => |*v| {
|
||||
// We ignore the message in case the title was set via config.
|
||||
if (self.config.title != null) {
|
||||
log.debug("ignoring title change request since static title is set via config", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
// The ptrCast just gets sliceTo to return the proper type.
|
||||
// We know that our title should end in 0.
|
||||
const slice = std.mem.sliceTo(@as([*:0]const u8, @ptrCast(v)), 0);
|
||||
|
@ -28,6 +28,7 @@ const UnsafePasteWindow = @import("UnsafePasteWindow.zig");
|
||||
const c = @import("c.zig");
|
||||
const inspector = @import("inspector.zig");
|
||||
const key = @import("key.zig");
|
||||
const testing = std.testing;
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
@ -103,9 +104,17 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
||||
// Our app ID determines uniqueness and maps to our desktop file.
|
||||
// We append "-debug" to the ID if we're in debug mode so that we
|
||||
// can develop Ghostty in Ghostty.
|
||||
const app_id: [:0]const u8 = comptime app_id: {
|
||||
var id = "com.mitchellh.ghostty";
|
||||
break :app_id if (builtin.mode == .Debug) id ++ "-debug" else id;
|
||||
const app_id: [:0]const u8 = app_id: {
|
||||
if (config.class) |class| {
|
||||
if (isValidAppId(class)) {
|
||||
break :app_id class;
|
||||
} else {
|
||||
log.warn("invalid 'class' in config, ignoring", .{});
|
||||
}
|
||||
}
|
||||
|
||||
const default_id = "com.mitchellh.ghostty";
|
||||
break :app_id if (builtin.mode == .Debug) default_id ++ "-debug" else default_id;
|
||||
};
|
||||
|
||||
// Create our GTK Application which encapsulates our process.
|
||||
@ -159,7 +168,6 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
||||
.config = config,
|
||||
.ctx = ctx,
|
||||
.cursor_none = cursor_none,
|
||||
|
||||
// If we are NOT the primary instance, then we never want to run.
|
||||
// This means that another instance of the GTK app is running and
|
||||
// our "activate" call above will open a window.
|
||||
@ -490,3 +498,32 @@ fn initMenu(self: *App) void {
|
||||
|
||||
self.menu = menu;
|
||||
}
|
||||
|
||||
fn isValidAppId(app_id: [:0]const u8) bool {
|
||||
if (app_id.len > 255 or app_id.len == 0) return false;
|
||||
if (app_id[0] == '.') return false;
|
||||
if (app_id[app_id.len - 1] == '.') return false;
|
||||
|
||||
var hasDot = false;
|
||||
for (app_id) |char| {
|
||||
switch (char) {
|
||||
'a'...'z', 'A'...'Z', '0'...'9', '_', '-' => {},
|
||||
'.' => hasDot = true,
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
if (!hasDot) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
test "isValidAppId" {
|
||||
try testing.expect(isValidAppId("foo.bar"));
|
||||
try testing.expect(isValidAppId("foo.bar.baz"));
|
||||
try testing.expect(!isValidAppId("foo"));
|
||||
try testing.expect(!isValidAppId("foo.bar?"));
|
||||
try testing.expect(!isValidAppId("foo."));
|
||||
try testing.expect(!isValidAppId(".foo"));
|
||||
try testing.expect(!isValidAppId(""));
|
||||
try testing.expect(!isValidAppId("foo" ** 86));
|
||||
}
|
||||
|
@ -123,6 +123,9 @@ pub fn init(self: *Window, app: *App) !void {
|
||||
}
|
||||
c.gtk_box_append(@ptrCast(box), notebook_widget);
|
||||
|
||||
// If we are in fullscreen mode, new windows start fullscreen.
|
||||
if (app.config.fullscreen) c.gtk_window_fullscreen(self.window);
|
||||
|
||||
// All of our events
|
||||
_ = c.g_signal_connect_data(window, "close-request", c.G_CALLBACK(>kCloseRequest), self, null, c.G_CONNECT_DEFAULT);
|
||||
_ = c.g_signal_connect_data(window, "destroy", c.G_CALLBACK(>kDestroy), self, null, c.G_CONNECT_DEFAULT);
|
||||
|
@ -278,6 +278,30 @@ command: ?[]const u8 = null,
|
||||
/// indicate that it is a login shell, depending on the OS).
|
||||
@"command-arg": RepeatableString = .{},
|
||||
|
||||
/// Start new windows in fullscreen. This setting applies to new
|
||||
/// windows and does not apply to tabs, splits, etc. However, this
|
||||
/// setting will apply to all new windows, not just the first one.
|
||||
///
|
||||
/// On macOS, this always creates the window in native fullscreen.
|
||||
/// Non-native fullscreen is not currently supported with this
|
||||
/// setting.
|
||||
fullscreen: bool = false,
|
||||
|
||||
/// The title Ghostty will use for the window. This will force the title
|
||||
/// of the window to be this title at all times and Ghostty will ignore any
|
||||
/// set title escape sequences programs (such as Neovim) may send.
|
||||
title: ?[:0]const u8 = null,
|
||||
|
||||
/// The setting that will change the application class value. This value is
|
||||
/// often used with Linux window managers to change behavior (such as
|
||||
/// floating vs tiled). If you don't know what this is, don't set it.
|
||||
///
|
||||
/// The class name must follow the GTK requirements defined here:
|
||||
/// https://docs.gtk.org/gio/type_func.Application.id_is_valid.html
|
||||
///
|
||||
/// This only affects GTK builds.
|
||||
class: ?[:0]const u8 = null,
|
||||
|
||||
/// The directory to change to after starting the command.
|
||||
///
|
||||
/// This setting is secondary to the "window-inherit-working-directory"
|
||||
|
Reference in New Issue
Block a user