mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
gtk: get 'Change Title' working with older distros
This commit is contained in:
@ -25,7 +25,7 @@ pub fn init(comptime name: []const u8, comptime kind: enum { blp, ui }) Builder
|
|||||||
// GResource.
|
// GResource.
|
||||||
const gresource = @import("gresource.zig");
|
const gresource = @import("gresource.zig");
|
||||||
for (gresource.blueprint_files) |blueprint_file| {
|
for (gresource.blueprint_files) |blueprint_file| {
|
||||||
if (std.mem.eql(u8, blueprint_file, name)) break;
|
if (std.mem.eql(u8, blueprint_file.name, name)) break;
|
||||||
} else @compileError("missing blueprint file '" ++ name ++ "' in gresource.zig");
|
} else @compileError("missing blueprint file '" ++ name ++ "' in gresource.zig");
|
||||||
},
|
},
|
||||||
.ui => {
|
.ui => {
|
||||||
|
@ -31,6 +31,7 @@ const inspector = @import("inspector.zig");
|
|||||||
const gtk_key = @import("key.zig");
|
const gtk_key = @import("key.zig");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
const Builder = @import("Builder.zig");
|
const Builder = @import("Builder.zig");
|
||||||
|
const adwaita = @import("adwaita.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.gtk_surface);
|
const log = std.log.scoped(.gtk_surface);
|
||||||
|
|
||||||
@ -1020,16 +1021,17 @@ fn resolveTitle(self: *Surface, title: [:0]const u8) [:0]const u8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn promptTitle(self: *Surface) !void {
|
pub fn promptTitle(self: *Surface) !void {
|
||||||
|
if (!adwaita.versionAtLeast(1, 5, 0)) return;
|
||||||
const window = self.container.window() orelse return;
|
const window = self.container.window() orelse return;
|
||||||
|
|
||||||
var builder = Builder.init("prompt-title-dialog", .blp);
|
var builder = Builder.init("prompt-title-dialog", .blp);
|
||||||
defer builder.deinit();
|
defer builder.deinit();
|
||||||
|
|
||||||
const entry: *gtk.Entry = @ptrCast(builder.getObject("title_entry"));
|
const entry = gobject.ext.cast(gtk.Entry, builder.getObject("title_entry").?).?;
|
||||||
entry.getBuffer().setText(self.getTitle() orelse "", -1);
|
entry.getBuffer().setText(self.getTitle() orelse "", -1);
|
||||||
|
|
||||||
const dialog: *adw.AlertDialog = @ptrCast(builder.getObject("prompt_title_dialog"));
|
const dialog = gobject.ext.cast(adw.AlertDialog, builder.getObject("prompt_title_dialog").?).?;
|
||||||
dialog.choose(@ptrCast(window.window), null, >kPromptTitleResponse, self);
|
dialog.choose(@ptrCast(window.window), null, gtkPromptTitleResponse, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the current working directory of the surface.
|
/// Set the current working directory of the surface.
|
||||||
@ -2320,12 +2322,13 @@ fn g_value_holds(value_: ?*c.GValue, g_type: c.GType) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gtkPromptTitleResponse(source_object: ?*gobject.Object, result: *gio.AsyncResult, ud: ?*anyopaque) callconv(.C) void {
|
fn gtkPromptTitleResponse(source_object: ?*gobject.Object, result: *gio.AsyncResult, ud: ?*anyopaque) callconv(.C) void {
|
||||||
const dialog: *adw.AlertDialog = @ptrCast(source_object.?);
|
if (!adwaita.versionAtLeast(1, 5, 0)) return;
|
||||||
const self = userdataSelf(ud.?);
|
const dialog = gobject.ext.cast(adw.AlertDialog, source_object.?).?;
|
||||||
|
const self = userdataSelf(ud orelse return);
|
||||||
|
|
||||||
const response = dialog.chooseFinish(result);
|
const response = dialog.chooseFinish(result);
|
||||||
if (std.mem.orderZ(u8, "ok", response) == .eq) {
|
if (std.mem.orderZ(u8, "ok", response) == .eq) {
|
||||||
const title_entry: *gtk.Entry = gobject.ext.cast(gtk.Entry, dialog.getExtraChild().?).?;
|
const title_entry = gobject.ext.cast(gtk.Entry, dialog.getExtraChild().?).?;
|
||||||
const title = std.mem.span(title_entry.getBuffer().getText());
|
const title = std.mem.span(title_entry.getBuffer().getText());
|
||||||
|
|
||||||
// if the new title is empty and the user has set the title previously, restore the terminal provided title
|
// if the new title is empty and the user has set the title previously, restore the terminal provided title
|
||||||
|
57
src/apprt/gtk/blueprint_compiler.zig
Normal file
57
src/apprt/gtk/blueprint_compiler.zig
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const c = @cImport({
|
||||||
|
@cInclude("adwaita.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
|
var it = try std.process.argsWithAllocator(alloc);
|
||||||
|
defer it.deinit();
|
||||||
|
|
||||||
|
_ = it.next();
|
||||||
|
|
||||||
|
const major = try std.fmt.parseUnsigned(u8, it.next() orelse return error.NoMajorVersion, 10);
|
||||||
|
const minor = try std.fmt.parseUnsigned(u8, it.next() orelse return error.NoMinorVersion, 10);
|
||||||
|
const micro = try std.fmt.parseUnsigned(u8, it.next() orelse return error.NoMicroVersion, 10);
|
||||||
|
const output = it.next() orelse return error.NoOutput;
|
||||||
|
const input = it.next() orelse return error.NoInput;
|
||||||
|
|
||||||
|
if (c.ADW_MAJOR_VERSION < major or
|
||||||
|
(c.ADW_MAJOR_VERSION == major and c.ADW_MINOR_VERSION < minor) or
|
||||||
|
(c.ADW_MAJOR_VERSION == major and c.ADW_MINOR_VERSION == minor and c.ADW_MICRO_VERSION < micro))
|
||||||
|
{
|
||||||
|
// If the Adwaita version is too old, generate an "empty" file.
|
||||||
|
const file = try std.fs.createFileAbsolute(output, .{
|
||||||
|
.truncate = true,
|
||||||
|
});
|
||||||
|
try file.writeAll(
|
||||||
|
\\<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
\\<interface domain="com.mitchellh.ghostty"/>
|
||||||
|
);
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var compiler = std.process.Child.init(
|
||||||
|
&.{
|
||||||
|
"blueprint-compiler",
|
||||||
|
"compile",
|
||||||
|
"--output",
|
||||||
|
output,
|
||||||
|
input,
|
||||||
|
},
|
||||||
|
alloc,
|
||||||
|
);
|
||||||
|
|
||||||
|
const term = try compiler.spawnAndWait();
|
||||||
|
switch (term) {
|
||||||
|
.Exited => |rc| {
|
||||||
|
if (rc != 0) std.posix.exit(1);
|
||||||
|
},
|
||||||
|
else => std.posix.exit(1),
|
||||||
|
}
|
||||||
|
}
|
@ -57,7 +57,17 @@ pub const ui_files = [_][]const u8{
|
|||||||
"menu-window-titlebar_menu",
|
"menu-window-titlebar_menu",
|
||||||
"menu-surface-context_menu",
|
"menu-surface-context_menu",
|
||||||
};
|
};
|
||||||
pub const blueprint_files = [_][]const u8{"prompt-title-dialog"};
|
|
||||||
|
pub const VersionedBlueprint = struct {
|
||||||
|
major: u16,
|
||||||
|
minor: u16,
|
||||||
|
micro: u16,
|
||||||
|
name: []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const blueprint_files = [_]VersionedBlueprint{
|
||||||
|
.{ .major = 1, .minor = 5, .micro = 0, .name = "prompt-title-dialog" },
|
||||||
|
};
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
@ -72,9 +82,9 @@ pub fn main() !void {
|
|||||||
var it = try std.process.argsWithAllocator(alloc);
|
var it = try std.process.argsWithAllocator(alloc);
|
||||||
defer it.deinit();
|
defer it.deinit();
|
||||||
|
|
||||||
while (it.next()) |filename| {
|
while (it.next()) |argument| {
|
||||||
if (std.mem.eql(u8, std.fs.path.extension(filename), ".ui")) {
|
if (std.mem.eql(u8, std.fs.path.extension(argument), ".ui")) {
|
||||||
try extra_ui_files.append(try alloc.dupe(u8, filename));
|
try extra_ui_files.append(try alloc.dupe(u8, argument));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +154,7 @@ pub const dependencies = deps: {
|
|||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
for (blueprint_files) |blueprint_file| {
|
for (blueprint_files) |blueprint_file| {
|
||||||
deps[index] = std.fmt.comptimePrint("src/apprt/gtk/ui/{s}.blp", .{blueprint_file});
|
deps[index] = std.fmt.comptimePrint("src/apprt/gtk/ui/{s}.blp", .{blueprint_file.name});
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
break :deps deps;
|
break :deps deps;
|
||||||
|
@ -6,8 +6,8 @@ Adw.AlertDialog prompt_title_dialog {
|
|||||||
body: _("Leave blank to restore the default title.");
|
body: _("Leave blank to restore the default title.");
|
||||||
|
|
||||||
responses [
|
responses [
|
||||||
cancel: _("Cancel"),
|
cancel: _("Cancel") suggested,
|
||||||
ok: _("OK") suggested
|
ok: _("OK") destructive
|
||||||
]
|
]
|
||||||
|
|
||||||
focus-widget: title_entry;
|
focus-widget: title_entry;
|
||||||
|
@ -443,6 +443,7 @@ pub fn add(
|
|||||||
.{ "glib", "glib2" },
|
.{ "glib", "glib2" },
|
||||||
.{ "gtk", "gtk4" },
|
.{ "gtk", "gtk4" },
|
||||||
.{ "gdk", "gdk4" },
|
.{ "gdk", "gdk4" },
|
||||||
|
.{ "adw", "adw1" },
|
||||||
};
|
};
|
||||||
inline for (gobject_imports) |import| {
|
inline for (gobject_imports) |import| {
|
||||||
const name, const module = import;
|
const name, const module = import;
|
||||||
@ -451,7 +452,6 @@ pub fn add(
|
|||||||
|
|
||||||
step.linkSystemLibrary2("gtk4", dynamic_link_opts);
|
step.linkSystemLibrary2("gtk4", dynamic_link_opts);
|
||||||
step.linkSystemLibrary2("libadwaita-1", dynamic_link_opts);
|
step.linkSystemLibrary2("libadwaita-1", dynamic_link_opts);
|
||||||
step.root_module.addImport("adw", gobject.module("adw1"));
|
|
||||||
|
|
||||||
if (self.config.x11) {
|
if (self.config.x11) {
|
||||||
step.linkSystemLibrary2("X11", dynamic_link_opts);
|
step.linkSystemLibrary2("X11", dynamic_link_opts);
|
||||||
@ -500,14 +500,24 @@ pub fn add(
|
|||||||
|
|
||||||
const generate = b.addRunArtifact(generate_gresource_xml);
|
const generate = b.addRunArtifact(generate_gresource_xml);
|
||||||
|
|
||||||
|
const gtk_blueprint_compiler = b.addExecutable(.{
|
||||||
|
.name = "gtk_blueprint_compiler",
|
||||||
|
.root_source_file = b.path("src/apprt/gtk/blueprint_compiler.zig"),
|
||||||
|
.target = b.host,
|
||||||
|
});
|
||||||
|
gtk_blueprint_compiler.linkSystemLibrary2("gtk4", dynamic_link_opts);
|
||||||
|
gtk_blueprint_compiler.linkSystemLibrary2("libadwaita-1", dynamic_link_opts);
|
||||||
|
gtk_blueprint_compiler.linkLibC();
|
||||||
|
|
||||||
for (gresource.blueprint_files) |blueprint_file| {
|
for (gresource.blueprint_files) |blueprint_file| {
|
||||||
const blueprint_compiler = b.addSystemCommand(&.{
|
const blueprint_compiler = b.addRunArtifact(gtk_blueprint_compiler);
|
||||||
"blueprint-compiler",
|
blueprint_compiler.addArgs(&.{
|
||||||
"compile",
|
b.fmt("{d}", .{blueprint_file.major}),
|
||||||
"--output",
|
b.fmt("{d}", .{blueprint_file.minor}),
|
||||||
|
b.fmt("{d}", .{blueprint_file.micro}),
|
||||||
});
|
});
|
||||||
const ui_file = blueprint_compiler.addOutputFileArg(b.fmt("{s}.ui", .{blueprint_file}));
|
const ui_file = blueprint_compiler.addOutputFileArg(b.fmt("{s}.ui", .{blueprint_file.name}));
|
||||||
blueprint_compiler.addFileArg(b.path(b.fmt("src/apprt/gtk/ui/{s}.blp", .{blueprint_file})));
|
blueprint_compiler.addFileArg(b.path(b.fmt("src/apprt/gtk/ui/{s}.blp", .{blueprint_file.name})));
|
||||||
generate.addFileArg(ui_file);
|
generate.addFileArg(ui_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,9 +5,11 @@ FROM docker.io/library/debian:${DISTRO_VERSION}
|
|||||||
RUN DEBIAN_FRONTEND="noninteractive" apt-get -qq update && \
|
RUN DEBIAN_FRONTEND="noninteractive" apt-get -qq update && \
|
||||||
apt-get -qq -y --no-install-recommends install \
|
apt-get -qq -y --no-install-recommends install \
|
||||||
# Build Tools
|
# Build Tools
|
||||||
|
blueprint-compiler \
|
||||||
build-essential \
|
build-essential \
|
||||||
libbz2-dev \
|
libbz2-dev \
|
||||||
libonig-dev \
|
libonig-dev \
|
||||||
|
libxml2-utils \
|
||||||
lintian \
|
lintian \
|
||||||
lsb-release \
|
lsb-release \
|
||||||
libxml2-utils \
|
libxml2-utils \
|
||||||
|
Reference in New Issue
Block a user