apprt/gtk: toggle_window_decorations keybinding

Fixes #1943
This commit is contained in:
Mitchell Hashimoto
2024-07-15 21:23:52 -07:00
parent cef4ef49ba
commit 2d7baaa7d7
5 changed files with 81 additions and 36 deletions

View File

@ -3504,6 +3504,12 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
} else log.warn("runtime doesn't implement toggleFullscreen", .{});
},
.toggle_window_decorations => {
if (@hasDecl(apprt.Surface, "toggleWindowDecorations")) {
self.rt_surface.toggleWindowDecorations();
} else log.warn("runtime doesn't implement toggleWindowDecorations", .{});
},
.select_all => {
const sel = self.io.terminal.screen.selectAll();
if (sel) |s| {

View File

@ -721,6 +721,18 @@ pub fn toggleFullscreen(self: *Surface, mac_non_native: configpkg.NonNativeFulls
window.toggleFullscreen(mac_non_native);
}
pub fn toggleWindowDecorations(self: *Surface) void {
const window = self.container.window() orelse {
log.info(
"toggleWindowDecorations invalid for container={s}",
.{@tagName(self.container)},
);
return;
};
window.toggleWindowDecorations();
}
pub fn getTitleLabel(self: *Surface) ?*c.GtkWidget {
switch (self.title) {
.none => return null,

View File

@ -77,31 +77,30 @@ pub fn init(self: *Window, app: *App) !void {
const display = c.gdk_display_get_default();
c.gtk_style_context_add_provider_for_display(display, @ptrCast(app.css_provider), c.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
// Use the new GTK4 header bar. We only create a header bar if we have
// window decorations.
if (app.config.@"window-decoration") {
// gtk-titlebar can also be used to disable the header bar (but keep
// the window manager's decorations).
if (app.config.@"gtk-titlebar") {
const header = c.gtk_header_bar_new();
c.gtk_window_set_titlebar(gtk_window, header);
{
const btn = c.gtk_menu_button_new();
c.gtk_widget_set_tooltip_text(btn, "Main Menu");
c.gtk_menu_button_set_icon_name(@ptrCast(btn), "open-menu-symbolic");
c.gtk_menu_button_set_menu_model(@ptrCast(btn), @ptrCast(@alignCast(app.menu)));
c.gtk_header_bar_pack_end(@ptrCast(header), btn);
}
{
const btn = c.gtk_button_new_from_icon_name("tab-new-symbolic");
c.gtk_widget_set_tooltip_text(btn, "New Tab");
c.gtk_header_bar_pack_end(@ptrCast(header), btn);
_ = c.g_signal_connect_data(btn, "clicked", c.G_CALLBACK(&gtkTabNewClick), self, null, c.G_CONNECT_DEFAULT);
}
// gtk-titlebar can be used to disable the header bar (but keep
// the window manager's decorations). We create this no matter if we
// are decorated or not because we can have a keybind to toggle the
// decorations.
if (app.config.@"gtk-titlebar") {
const header = c.gtk_header_bar_new();
c.gtk_window_set_titlebar(gtk_window, header);
{
const btn = c.gtk_menu_button_new();
c.gtk_widget_set_tooltip_text(btn, "Main Menu");
c.gtk_menu_button_set_icon_name(@ptrCast(btn), "open-menu-symbolic");
c.gtk_menu_button_set_menu_model(@ptrCast(btn), @ptrCast(@alignCast(app.menu)));
c.gtk_header_bar_pack_end(@ptrCast(header), btn);
}
} else {
// Hide window decoration if configured. This has to happen before
// `gtk_widget_show`.
{
const btn = c.gtk_button_new_from_icon_name("tab-new-symbolic");
c.gtk_widget_set_tooltip_text(btn, "New Tab");
c.gtk_header_bar_pack_end(@ptrCast(header), btn);
_ = c.g_signal_connect_data(btn, "clicked", c.G_CALLBACK(&gtkTabNewClick), self, null, c.G_CONNECT_DEFAULT);
}
}
// If we are disabling decorations then disable them right away.
if (!app.config.@"window-decoration") {
c.gtk_window_set_decorated(gtk_window, 0);
}
@ -296,6 +295,15 @@ pub fn toggleFullscreen(self: *Window, _: configpkg.NonNativeFullscreen) void {
}
}
/// Toggle the window decorations for this window.
pub fn toggleWindowDecorations(self: *Window) void {
if (c.gtk_window_get_decorated(self.window) == 0) {
c.gtk_window_set_decorated(self.window, 1);
} else {
c.gtk_window_set_decorated(self.window, 0);
}
}
/// Grabs focus on the currently selected tab.
fn focusCurrentTab(self: *Window) void {
const page_idx = c.gtk_notebook_get_current_page(self.notebook);

View File

@ -571,6 +571,11 @@ class: ?[:0]const u8 = null,
///
/// * only a single key input is allowed, `ctrl+a+b` is invalid.
///
/// * the key input can be prefixed with `physical:` to specify a
/// physical key mapping rather than a logical one. A physical key
/// mapping responds to the hardware keycode and not the keycode
/// translated by any system keyboard layouts. Example: "ctrl+physical:a"
///
/// Valid modifiers are `shift`, `ctrl` (alias: `control`), `alt` (alias: `opt`,
/// `option`), and `super` (alias: `cmd`, `command`). You may use the modifier
/// or the alias. When debugging keybinds, the non-aliased modifier will always
@ -608,6 +613,12 @@ class: ?[:0]const u8 = null,
/// * `keybind=clear` will clear all set keybindings. Warning: this
/// removes ALL keybindings up to this point, including the default
/// keybindings.
///
/// A keybind by default causes the input to be consumed. This means that the
/// associated encoding (if any) will not be sent to the running program
/// in the terminal. If you wish to send the encoded value to the program,
/// specify the "unconsumed:" prefix before the entire keybind. For example:
/// "unconsumed:ctrl+a=reload_config"
keybind: Keybinds = .{},
/// Window padding. This applies padding between the terminal cells and the
@ -669,7 +680,12 @@ keybind: Keybinds = .{},
/// * `true`
/// * `false` - windows won't have native decorations, i.e. titlebar and
/// borders. On MacOS this also disables tabs and tab overview.
///
/// The "toggle_window_decoration" keybind action can be used to create
/// a keybinding to toggle this setting at runtime.
///
/// Changing this configuration in your configuration and reloading will
/// only affect new windows. Existing windows will not be affected.
@"window-decoration": bool = true,
/// The font that will be used for the application's window and tab titles.
@ -781,17 +797,6 @@ keybind: Keybinds = .{},
// Default is false.
@"focus-follows-mouse": bool = false,
/// When enabled, the full GTK titlebar is displayed instead of your window
/// manager's simple titlebar. The behavior of this option will vary with your
/// window manager.
///
/// This option does nothing when `window-decoration` is false or when running
/// under macOS.
///
/// Changing this value at runtime and reloading the configuration will only
/// affect new windows.
@"gtk-titlebar": bool = true,
/// Whether to allow programs running in the terminal to read/write to the
/// system clipboard (OSC 52, for googling). The default is to allow clipboard
/// reading after prompting the user and allow writing unconditionally.
@ -1102,6 +1107,17 @@ keybind: Keybinds = .{},
/// so you can test single instance without conflicting with release builds.
@"gtk-single-instance": GtkSingleInstance = .desktop,
/// When enabled, the full GTK titlebar is displayed instead of your window
/// manager's simple titlebar. The behavior of this option will vary with your
/// window manager.
///
/// This option does nothing when `window-decoration` is false or when running
/// under macOS.
///
/// Changing this value at runtime and reloading the configuration will only
/// affect new windows.
@"gtk-titlebar": bool = true,
/// Determines the side of the screen that the GTK tab bar will stick to.
/// Top, bottom, left, and right are supported. The default is top.
@"gtk-tabs-location": GtkTabsLocation = .top,

View File

@ -266,6 +266,9 @@ pub const Action = union(enum) {
/// Toggle fullscreen mode of window.
toggle_fullscreen: void,
/// Toggle window decorations on and off. This only works on Linux.
toggle_window_decorations: void,
/// Quit ghostty.
quit: void,