mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
tweaks to window position
This commit is contained in:
@ -273,6 +273,28 @@ class TerminalController: BaseTerminalController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func setInitialWindowPosition(x: Int16?, y: Int16?, windowDecorations: Bool) {
|
||||||
|
guard let window else { return }
|
||||||
|
|
||||||
|
// If we don't have both an X and Y we center.
|
||||||
|
guard let x, let y else {
|
||||||
|
window.center()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefer the screen our window is being placed on otherwise our primary screen.
|
||||||
|
guard let screen = window.screen ?? NSScreen.screens.first else {
|
||||||
|
window.center()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orient based on the top left of the primary monitor
|
||||||
|
let frame = screen.visibleFrame
|
||||||
|
window.setFrameOrigin(.init(
|
||||||
|
x: frame.minX + CGFloat(x),
|
||||||
|
y: frame.maxY - (CGFloat(y) + window.frame.height)))
|
||||||
|
}
|
||||||
|
|
||||||
//MARK: - NSWindowController
|
//MARK: - NSWindowController
|
||||||
|
|
||||||
override func windowWillLoad() {
|
override func windowWillLoad() {
|
||||||
@ -370,8 +392,11 @@ class TerminalController: BaseTerminalController {
|
|||||||
|
|
||||||
// Set our window positioning to coordinates if config value exists, otherwise
|
// Set our window positioning to coordinates if config value exists, otherwise
|
||||||
// fallback to original centering behavior
|
// fallback to original centering behavior
|
||||||
setInitialWindowPosition(window, x: config.windowInitialPositionX, y: config.windowInitialPositionY, windowDecorations: config.windowDecorations)
|
setInitialWindowPosition(
|
||||||
|
x: config.windowPositionX,
|
||||||
|
y: config.windowPositionY,
|
||||||
|
windowDecorations: config.windowDecorations)
|
||||||
|
|
||||||
// Make sure our theme is set on the window so styling is correct.
|
// Make sure our theme is set on the window so styling is correct.
|
||||||
if let windowTheme = config.windowTheme {
|
if let windowTheme = config.windowTheme {
|
||||||
window.windowTheme = .init(rawValue: windowTheme)
|
window.windowTheme = .init(rawValue: windowTheme)
|
||||||
@ -468,31 +493,6 @@ class TerminalController: BaseTerminalController {
|
|||||||
let data = TerminalRestorableState(from: self)
|
let data = TerminalRestorableState(from: self)
|
||||||
data.encode(with: state)
|
data.encode(with: state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setInitialWindowPosition(_ window: NSWindow, x: Int16?, y: Int16?, windowDecorations: Bool) {
|
|
||||||
if let primaryScreen = NSScreen.screens.first {
|
|
||||||
let frame = primaryScreen.visibleFrame
|
|
||||||
|
|
||||||
if let windowPositionX = x, let windowPositionY = y {
|
|
||||||
// Offset titlebar if needed, otherwise use default padding of 12
|
|
||||||
// NOTE: Not 100% certain where this extra padding comes from but I'd love
|
|
||||||
// to calculate it dynamically if possible
|
|
||||||
let titlebarHeight = windowDecorations ? window.frame.height - (window.contentView?.frame.height ?? 0) : 12
|
|
||||||
|
|
||||||
// Orient based on the top left of the primary monitor
|
|
||||||
let startPositionX = frame.origin.x + CGFloat(windowPositionX)
|
|
||||||
let startPositionY = (frame.origin.y + frame.height) - (CGFloat(windowPositionY) + window.frame.height) + titlebarHeight
|
|
||||||
|
|
||||||
window.setFrameOrigin(NSPoint(x: startPositionX, y: startPositionY))
|
|
||||||
} else {
|
|
||||||
// Fallback to original centering behavior
|
|
||||||
window.center()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Fallback to original centering behavior
|
|
||||||
window.center()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: First Responder
|
// MARK: First Responder
|
||||||
|
|
||||||
|
@ -150,17 +150,17 @@ extension Ghostty {
|
|||||||
return String(cString: ptr)
|
return String(cString: ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var windowInitialPositionX: Int16? {
|
var windowPositionX: Int16? {
|
||||||
guard let config = self.config else { return nil }
|
guard let config = self.config else { return nil }
|
||||||
var v: Int16 = 0
|
var v: Int16 = 0
|
||||||
let key = "window-initial-position-x"
|
let key = "window-position-x"
|
||||||
return ghostty_config_get(config, &v, key, UInt(key.count)) ? v : nil
|
return ghostty_config_get(config, &v, key, UInt(key.count)) ? v : nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var windowInitialPositionY: Int16? {
|
var windowPositionY: Int16? {
|
||||||
guard let config = self.config else { return nil }
|
guard let config = self.config else { return nil }
|
||||||
var v: Int16 = 0
|
var v: Int16 = 0
|
||||||
let key = "window-initial-position-y"
|
let key = "window-position-y"
|
||||||
return ghostty_config_get(config, &v, key, UInt(key.count)) ? v : nil
|
return ghostty_config_get(config, &v, key, UInt(key.count)) ? v : nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,14 +149,10 @@ pub const App = struct {
|
|||||||
value: apprt.Action.Value(action),
|
value: apprt.Action.Value(action),
|
||||||
) !void {
|
) !void {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
.new_window => {
|
.new_window => _ = try self.newSurface(switch (target) {
|
||||||
var surface = try self.newSurface(switch (target) {
|
.app => null,
|
||||||
.app => null,
|
.surface => |v| v,
|
||||||
.surface => |v| v,
|
}),
|
||||||
});
|
|
||||||
|
|
||||||
try surface.setInitialWindowPosition(self.config.@"window-initial-position-x", self.config.@"window-initial-position-y");
|
|
||||||
},
|
|
||||||
|
|
||||||
.new_tab => try self.newTab(switch (target) {
|
.new_tab => try self.newTab(switch (target) {
|
||||||
.app => null,
|
.app => null,
|
||||||
@ -514,6 +510,13 @@ pub const Surface = struct {
|
|||||||
) orelse return glfw.mustGetErrorCode();
|
) orelse return glfw.mustGetErrorCode();
|
||||||
errdefer win.destroy();
|
errdefer win.destroy();
|
||||||
|
|
||||||
|
// Setup our
|
||||||
|
setInitialWindowPosition(
|
||||||
|
win,
|
||||||
|
app.config.@"window-position-x",
|
||||||
|
app.config.@"window-position-y",
|
||||||
|
);
|
||||||
|
|
||||||
// Get our physical DPI - debug only because we don't have a use for
|
// Get our physical DPI - debug only because we don't have a use for
|
||||||
// this but the logging of it may be useful
|
// this but the logging of it may be useful
|
||||||
if (builtin.mode == .Debug) {
|
if (builtin.mode == .Debug) {
|
||||||
@ -670,12 +673,12 @@ pub const Surface = struct {
|
|||||||
/// Set the initial window position. This is called exactly once at
|
/// Set the initial window position. This is called exactly once at
|
||||||
/// surface initialization time. This may be called before "self"
|
/// surface initialization time. This may be called before "self"
|
||||||
/// is fully initialized.
|
/// is fully initialized.
|
||||||
fn setInitialWindowPosition(self: *const Surface, x: ?i16, y: ?i16) !void {
|
fn setInitialWindowPosition(win: glfw.Window, x: ?i16, y: ?i16) void {
|
||||||
const start_position_x = x orelse return;
|
const start_position_x = x orelse return;
|
||||||
const start_position_y = y orelse return;
|
const start_position_y = y orelse return;
|
||||||
|
|
||||||
log.debug("setting initial window position ({},{})", .{ start_position_x, start_position_y });
|
log.debug("setting initial window position ({},{})", .{ start_position_x, start_position_y });
|
||||||
self.window.setPos(.{ .x = start_position_x, .y = start_position_y });
|
win.setPos(.{ .x = start_position_x, .y = start_position_y });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the size limits of the window.
|
/// Set the size limits of the window.
|
||||||
|
@ -1108,7 +1108,7 @@ keybind: Keybinds = .{},
|
|||||||
@"window-height": u32 = 0,
|
@"window-height": u32 = 0,
|
||||||
@"window-width": u32 = 0,
|
@"window-width": u32 = 0,
|
||||||
|
|
||||||
/// The initial window position. This position is in pixels and is relative
|
/// The starting window position. This position is in pixels and is relative
|
||||||
/// to the top-left corner of the primary monitor. Both values must be set to take
|
/// to the top-left corner of the primary monitor. Both values must be set to take
|
||||||
/// effect. If only one value is set, it is ignored.
|
/// effect. If only one value is set, it is ignored.
|
||||||
///
|
///
|
||||||
@ -1117,10 +1117,22 @@ keybind: Keybinds = .{},
|
|||||||
/// to be a certain position to fit within the grid. There is nothing Ghostty
|
/// to be a certain position to fit within the grid. There is nothing Ghostty
|
||||||
/// will do about this, but it will make an effort.
|
/// will do about this, but it will make an effort.
|
||||||
///
|
///
|
||||||
/// Important note: Setting this value will only work on macOS and glfw builds
|
/// Also note that negative values are also up to the operating system and
|
||||||
/// on Linux. GTK 4.0 does not support setting the window position.
|
/// window manager. Some window managers may not allow windows to be placed
|
||||||
@"window-initial-position-x": ?i16 = null,
|
/// off-screen.
|
||||||
@"window-initial-position-y": ?i16 = null,
|
///
|
||||||
|
/// Invalid positions are runtime-specific, but generally the positions are
|
||||||
|
/// clamped to the nearest valid position.
|
||||||
|
///
|
||||||
|
/// On macOS, the window position is relative to the top-left corner of
|
||||||
|
/// the visible screen area. This means that if the menu bar is visible, the
|
||||||
|
/// window will be placed below the menu bar.
|
||||||
|
///
|
||||||
|
/// Note: this is only supported on macOS and Linux GLFW builds. The GTK
|
||||||
|
/// runtime does not support setting the window position (this is a limitation
|
||||||
|
/// of GTK 4.0).
|
||||||
|
@"window-position-x": ?i16 = null,
|
||||||
|
@"window-position-y": ?i16 = null,
|
||||||
|
|
||||||
/// Whether to enable saving and restoring window state. Window state includes
|
/// Whether to enable saving and restoring window state. Window state includes
|
||||||
/// their position, size, tabs, splits, etc. Some window state requires shell
|
/// their position, size, tabs, splits, etc. Some window state requires shell
|
||||||
|
Reference in New Issue
Block a user