mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-06-14 07:33:58 +00:00
Merge remote-tracking branch 'upstream/main' into coretext-position-y
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -4,7 +4,6 @@ build.zig.zon.json linguist-generated=true
|
||||
vendor/** linguist-vendored
|
||||
website/** linguist-documentation
|
||||
pkg/breakpad/vendor/** linguist-vendored
|
||||
pkg/cimgui/vendor/** linguist-vendored
|
||||
pkg/glfw/wayland-headers/** linguist-vendored
|
||||
pkg/libintl/config.h linguist-generated=true
|
||||
pkg/libintl/libintl.h linguist-generated=true
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
},
|
||||
|
||||
// C libs
|
||||
.cimgui = .{ .path = "./pkg/cimgui", .lazy = true },
|
||||
.dcimgui = .{ .path = "./pkg/dcimgui", .lazy = true },
|
||||
.fontconfig = .{ .path = "./pkg/fontconfig", .lazy = true },
|
||||
.freetype = .{ .path = "./pkg/freetype", .lazy = true },
|
||||
.gtk4_layer_shell = .{ .path = "./pkg/gtk4-layer-shell", .lazy = true },
|
||||
|
||||
11
build.zig.zon.json
generated
11
build.zig.zon.json
generated
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"N-V-__8AANT61wB--nJ95Gj_ctmzAtcjloZ__hRqNw5lC1Kr": {
|
||||
"name": "bindings",
|
||||
"url": "https://deps.files.ghostty.org/DearBindings_v0.17_ImGui_v1.92.5-docking.tar.gz",
|
||||
"hash": "sha256-i/7FAOAJJvZ5hT7iPWfMOS08MYFzPKRwRzhlHT9wuqM="
|
||||
},
|
||||
"N-V-__8AALw2uwF_03u4JRkZwRLc3Y9hakkYV7NKRR9-RIZJ": {
|
||||
"name": "breakpad",
|
||||
"url": "https://deps.files.ghostty.org/breakpad-b99f444ba5f6b98cac261cbb391d8766b34a5918.tar.gz",
|
||||
@@ -44,10 +49,10 @@
|
||||
"url": "https://deps.files.ghostty.org/highway-66486a10623fa0d72fe91260f96c892e41aceb06.tar.gz",
|
||||
"hash": "sha256-h9T4iT704I8iSXNgj/6/lCaKgTgLp5wS6IQZaMgKohI="
|
||||
},
|
||||
"N-V-__8AAH0GaQC8a52s6vfIxg88OZgFgEW6DFxfSK4lX_l3": {
|
||||
"N-V-__8AAEbOfQBnvcFcCX2W5z7tDaN8vaNZGamEQtNOe0UI": {
|
||||
"name": "imgui",
|
||||
"url": "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz",
|
||||
"hash": "sha256-oF/QHgTPEat4Hig4fGIdLkIPHmBEyOJ6JeYD6pnveGA="
|
||||
"url": "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.5-docking.tar.gz",
|
||||
"hash": "sha256-yBbCDox18+Fa6Gc1DnmSVQLRpqhZOLsac7iSfl8x+cs="
|
||||
},
|
||||
"N-V-__8AAIdIAwAOceDblkuOARUyuTKbDdGPjPClPLhMeIfU": {
|
||||
"name": "iterm2_themes",
|
||||
|
||||
14
build.zig.zon.nix
generated
14
build.zig.zon.nix
generated
@@ -82,6 +82,14 @@
|
||||
fetcher.${proto};
|
||||
in
|
||||
linkFarm name [
|
||||
{
|
||||
name = "N-V-__8AANT61wB--nJ95Gj_ctmzAtcjloZ__hRqNw5lC1Kr";
|
||||
path = fetchZigArtifact {
|
||||
name = "bindings";
|
||||
url = "https://deps.files.ghostty.org/DearBindings_v0.17_ImGui_v1.92.5-docking.tar.gz";
|
||||
hash = "sha256-i/7FAOAJJvZ5hT7iPWfMOS08MYFzPKRwRzhlHT9wuqM=";
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "N-V-__8AALw2uwF_03u4JRkZwRLc3Y9hakkYV7NKRR9-RIZJ";
|
||||
path = fetchZigArtifact {
|
||||
@@ -155,11 +163,11 @@ in
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "N-V-__8AAH0GaQC8a52s6vfIxg88OZgFgEW6DFxfSK4lX_l3";
|
||||
name = "N-V-__8AAEbOfQBnvcFcCX2W5z7tDaN8vaNZGamEQtNOe0UI";
|
||||
path = fetchZigArtifact {
|
||||
name = "imgui";
|
||||
url = "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz";
|
||||
hash = "sha256-oF/QHgTPEat4Hig4fGIdLkIPHmBEyOJ6JeYD6pnveGA=";
|
||||
url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.5-docking.tar.gz";
|
||||
hash = "sha256-yBbCDox18+Fa6Gc1DnmSVQLRpqhZOLsac7iSfl8x+cs=";
|
||||
};
|
||||
}
|
||||
{
|
||||
|
||||
3
build.zig.zon.txt
generated
3
build.zig.zon.txt
generated
@@ -1,4 +1,5 @@
|
||||
git+https://github.com/jacobsandlund/uucode#5f05f8f83a75caea201f12cc8ea32a2d82ea9732
|
||||
https://deps.files.ghostty.org/DearBindings_v0.17_ImGui_v1.92.5-docking.tar.gz
|
||||
https://deps.files.ghostty.org/JetBrainsMono-2.304.tar.gz
|
||||
https://deps.files.ghostty.org/NerdFontsSymbolsOnly-3.4.0.tar.gz
|
||||
https://deps.files.ghostty.org/breakpad-b99f444ba5f6b98cac261cbb391d8766b34a5918.tar.gz
|
||||
@@ -11,7 +12,6 @@ https://deps.files.ghostty.org/gobject-2025-11-08-23-1.tar.zst
|
||||
https://deps.files.ghostty.org/gtk4-layer-shell-1.1.0.tar.gz
|
||||
https://deps.files.ghostty.org/harfbuzz-11.0.0.tar.xz
|
||||
https://deps.files.ghostty.org/highway-66486a10623fa0d72fe91260f96c892e41aceb06.tar.gz
|
||||
https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz
|
||||
https://deps.files.ghostty.org/libpng-1220aa013f0c83da3fb64ea6d327f9173fa008d10e28bc9349eac3463457723b1c66.tar.gz
|
||||
https://deps.files.ghostty.org/libxev-34fa50878aec6e5fa8f532867001ab3c36fae23e.tar.gz
|
||||
https://deps.files.ghostty.org/libxml2-2.11.5.tar.gz
|
||||
@@ -32,4 +32,5 @@ https://deps.files.ghostty.org/zig_objc-f356ed02833f0f1b8e84d50bed9e807bf7cdc0ae
|
||||
https://deps.files.ghostty.org/zig_wayland-1b5c038ec10da20ed3a15b0b2a6db1c21383e8ea.tar.gz
|
||||
https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz
|
||||
https://github.com/ivanstepanovftw/zigimg/archive/d7b7ab0ba0899643831ef042bd73289510b39906.tar.gz
|
||||
https://github.com/ocornut/imgui/archive/refs/tags/v1.92.5-docking.tar.gz
|
||||
https://github.com/vancluever/z2d/archive/refs/tags/v0.10.0.tar.gz
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
[
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://deps.files.ghostty.org/DearBindings_v0.17_ImGui_v1.92.5-docking.tar.gz",
|
||||
"dest": "vendor/p/N-V-__8AANT61wB--nJ95Gj_ctmzAtcjloZ__hRqNw5lC1Kr",
|
||||
"sha256": "8bfec500e00926f679853ee23d67cc392d3c3181733ca4704738651d3f70baa3"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://deps.files.ghostty.org/breakpad-b99f444ba5f6b98cac261cbb391d8766b34a5918.tar.gz",
|
||||
@@ -55,9 +61,9 @@
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz",
|
||||
"dest": "vendor/p/N-V-__8AAH0GaQC8a52s6vfIxg88OZgFgEW6DFxfSK4lX_l3",
|
||||
"sha256": "a05fd01e04cf11ab781e28387c621d2e420f1e6044c8e27a25e603ea99ef7860"
|
||||
"url": "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.5-docking.tar.gz",
|
||||
"dest": "vendor/p/N-V-__8AAEbOfQBnvcFcCX2W5z7tDaN8vaNZGamEQtNOe0UI",
|
||||
"sha256": "c816c20e8c75f3e15ae867350e79925502d1a6a85938bb1a73b8927e5f31f9cb"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
|
||||
@@ -152,7 +152,6 @@
|
||||
Helpers/AppInfo.swift,
|
||||
Helpers/CodableBridge.swift,
|
||||
Helpers/Cursor.swift,
|
||||
Helpers/DraggableWindowView.swift,
|
||||
Helpers/ExpiringUndoManager.swift,
|
||||
"Helpers/Extensions/Double+Extension.swift",
|
||||
"Helpers/Extensions/EventModifiers+Extension.swift",
|
||||
|
||||
@@ -952,7 +952,7 @@ class BaseTerminalController: NSWindowController,
|
||||
// controller is a TerminalController this is easy because it has a way
|
||||
// to do this.
|
||||
if let c = sourceController as? TerminalController {
|
||||
c.closeWindowImmediately()
|
||||
c.closeTabImmediately()
|
||||
} else {
|
||||
// Not a TerminalController so we always undo into a new window.
|
||||
_ = TerminalController.newWindow(
|
||||
|
||||
@@ -614,7 +614,7 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||
closeWindow(nil)
|
||||
}
|
||||
|
||||
private func closeTabImmediately(registerRedo: Bool = true) {
|
||||
func closeTabImmediately(registerRedo: Bool = true) {
|
||||
guard let window = window else { return }
|
||||
guard let tabGroup = window.tabGroup,
|
||||
tabGroup.windows.count > 1 else {
|
||||
|
||||
@@ -194,7 +194,7 @@ class TerminalWindow: NSWindow {
|
||||
|
||||
// Its possible we miss the accessory titlebar call so we check again
|
||||
// whenever the window becomes main. Both of these are idempotent.
|
||||
if hasTabBar {
|
||||
if tabBarView != nil {
|
||||
tabBarDidAppear()
|
||||
} else {
|
||||
tabBarDidDisappear()
|
||||
@@ -243,31 +243,6 @@ class TerminalWindow: NSWindow {
|
||||
/// added.
|
||||
static let tabBarIdentifier: NSUserInterfaceItemIdentifier = .init("_ghosttyTabBar")
|
||||
|
||||
func findTitlebarView() -> NSView? {
|
||||
// Find our tab bar. If it doesn't exist we don't do anything.
|
||||
//
|
||||
// In normal window, `NSTabBar` typically appears as a subview of `NSTitlebarView` within `NSThemeFrame`.
|
||||
// In fullscreen, the system creates a dedicated fullscreen window and the view hierarchy changes;
|
||||
// in that case, the `titlebarView` is only accessible via a reference on `NSThemeFrame`.
|
||||
// ref: https://github.com/mozilla-firefox/firefox/blob/054e2b072785984455b3b59acad9444ba1eeffb4/widget/cocoa/nsCocoaWindow.mm#L7205
|
||||
guard let themeFrameView = contentView?.rootView else { return nil }
|
||||
let titlebarView = if themeFrameView.responds(to: Selector(("titlebarView"))) {
|
||||
themeFrameView.value(forKey: "titlebarView") as? NSView
|
||||
} else {
|
||||
NSView?.none
|
||||
}
|
||||
return titlebarView
|
||||
}
|
||||
|
||||
func findTabBar() -> NSView? {
|
||||
findTitlebarView()?.firstDescendant(withClassName: "NSTabBar")
|
||||
}
|
||||
|
||||
/// Returns true if there is a tab bar visible on this window.
|
||||
var hasTabBar: Bool {
|
||||
findTabBar() != nil
|
||||
}
|
||||
|
||||
var hasMoreThanOneTabs: Bool {
|
||||
/// accessing ``tabGroup?.windows`` here
|
||||
/// will cause other edge cases, be careful
|
||||
|
||||
@@ -85,7 +85,7 @@ class TitlebarTabsTahoeTerminalWindow: TransparentTitlebarTerminalWindow, NSTool
|
||||
return
|
||||
}
|
||||
|
||||
guard let tabBarView = findTabBar() else {
|
||||
guard let tabBarView else {
|
||||
super.sendEvent(event)
|
||||
return
|
||||
}
|
||||
@@ -176,8 +176,8 @@ class TitlebarTabsTahoeTerminalWindow: TransparentTitlebarTerminalWindow, NSTool
|
||||
guard tabBarObserver == nil else { return }
|
||||
|
||||
guard
|
||||
let titlebarView = findTitlebarView(),
|
||||
let tabBar = findTabBar()
|
||||
let titlebarView,
|
||||
let tabBarView = self.tabBarView
|
||||
else { return }
|
||||
|
||||
// View model updates must happen on their own ticks.
|
||||
@@ -186,13 +186,13 @@ class TitlebarTabsTahoeTerminalWindow: TransparentTitlebarTerminalWindow, NSTool
|
||||
}
|
||||
|
||||
// Find our clip view
|
||||
guard let clipView = tabBar.firstSuperview(withClassName: "NSTitlebarAccessoryClipView") else { return }
|
||||
guard let clipView = tabBarView.firstSuperview(withClassName: "NSTitlebarAccessoryClipView") else { return }
|
||||
guard let accessoryView = clipView.subviews[safe: 0] else { return }
|
||||
guard let toolbarView = titlebarView.firstDescendant(withClassName: "NSToolbarView") else { return }
|
||||
|
||||
// Make sure tabBar's height won't be stretched
|
||||
guard let newTabButton = titlebarView.firstDescendant(withClassName: "NSTabBarNewTabButton") else { return }
|
||||
tabBar.frame.size.height = newTabButton.frame.width
|
||||
tabBarView.frame.size.height = newTabButton.frame.width
|
||||
|
||||
// The container is the view that we'll constrain our tab bar within.
|
||||
let container = toolbarView
|
||||
@@ -228,10 +228,10 @@ class TitlebarTabsTahoeTerminalWindow: TransparentTitlebarTerminalWindow, NSTool
|
||||
// other events occur, the tab bar can resize and clear our constraints. When this
|
||||
// happens, we need to remove our custom constraints and re-apply them once the
|
||||
// tab bar has proper dimensions again to avoid constraint conflicts.
|
||||
tabBar.postsFrameChangedNotifications = true
|
||||
tabBarView.postsFrameChangedNotifications = true
|
||||
tabBarObserver = NotificationCenter.default.addObserver(
|
||||
forName: NSView.frameDidChangeNotification,
|
||||
object: tabBar,
|
||||
object: tabBarView,
|
||||
queue: .main
|
||||
) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
|
||||
@@ -104,19 +104,31 @@ extension Ghostty {
|
||||
|
||||
/// Whether the current drag was cancelled by pressing escape.
|
||||
private var dragCancelledByEscape: Bool = false
|
||||
|
||||
|
||||
deinit {
|
||||
if let escapeMonitor {
|
||||
NSEvent.removeMonitor(escapeMonitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override func acceptsFirstMouse(for event: NSEvent?) -> Bool {
|
||||
// Ensure this view gets the mouse event before window dragging handlers
|
||||
return true
|
||||
}
|
||||
|
||||
override func mouseDown(with event: NSEvent) {
|
||||
// Consume the mouseDown event to prevent it from propagating to the
|
||||
// window's drag handler. This fixes issue #10110 where grab handles
|
||||
// would drag the window instead of initiating pane drags.
|
||||
// Don't call super - the drag will be initiated in mouseDragged.
|
||||
}
|
||||
|
||||
override func updateTrackingAreas() {
|
||||
super.updateTrackingAreas()
|
||||
|
||||
|
||||
// To update our tracking area we just recreate it all.
|
||||
trackingAreas.forEach { removeTrackingArea($0) }
|
||||
|
||||
|
||||
// Add our tracking area for mouse events
|
||||
addTrackingArea(NSTrackingArea(
|
||||
rect: bounds,
|
||||
@@ -225,7 +237,7 @@ extension Ghostty {
|
||||
NSEvent.removeMonitor(escapeMonitor)
|
||||
self.escapeMonitor = nil
|
||||
}
|
||||
|
||||
|
||||
if operation == [] && !dragCancelledByEscape {
|
||||
let endsInWindow = NSApplication.shared.windows.contains { window in
|
||||
window.isVisible && window.frame.contains(screenPoint)
|
||||
@@ -238,7 +250,7 @@ extension Ghostty {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
isTracking = false
|
||||
onDragStateChanged?(false)
|
||||
}
|
||||
|
||||
@@ -1181,16 +1181,9 @@ extension Ghostty {
|
||||
|
||||
/// Special case handling for some control keys
|
||||
override func performKeyEquivalent(with event: NSEvent) -> Bool {
|
||||
switch (event.type) {
|
||||
case .keyDown:
|
||||
// Continue, we care about key down events
|
||||
break
|
||||
|
||||
default:
|
||||
// Any other key event we don't care about. I don't think its even
|
||||
// possible to receive any other event type.
|
||||
return false
|
||||
}
|
||||
// We only care about key down events. It might not even be possible
|
||||
// to receive any other event type here.
|
||||
guard event.type == .keyDown else { return false }
|
||||
|
||||
// Only process events if we're focused. Some key events like C-/ macOS
|
||||
// appears to send to the first view in the hierarchy rather than the
|
||||
@@ -1202,7 +1195,15 @@ extension Ghostty {
|
||||
return false
|
||||
}
|
||||
|
||||
// If this event as-is would result in a key binding then we send it.
|
||||
// Let the menu system handle this event if we're not in a key sequence or key table.
|
||||
// This allows the menu bar to flash for shortcuts like Command+V.
|
||||
if keySequence.isEmpty && keyTables.isEmpty {
|
||||
if let menu = NSApp.mainMenu, menu.performKeyEquivalent(with: event) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// If the menu didn't handle it, check Ghostty bindings for custom shortcuts.
|
||||
if let surface {
|
||||
var ghosttyEvent = event.ghosttyKeyEvent(GHOSTTY_ACTION_PRESS)
|
||||
let match = (event.characters ?? "").withCString { ptr in
|
||||
@@ -2216,7 +2217,7 @@ extension Ghostty.SurfaceView {
|
||||
|
||||
return NSAttributedString(string: plainString, attributes: attributes)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// Caches a value for some period of time, evicting it automatically when that time expires.
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import Cocoa
|
||||
import SwiftUI
|
||||
|
||||
struct DraggableWindowView: NSViewRepresentable {
|
||||
func makeNSView(context: Context) -> DraggableWindowNSView {
|
||||
return DraggableWindowNSView()
|
||||
}
|
||||
|
||||
func updateNSView(_ nsView: DraggableWindowNSView, context: Context) {
|
||||
// No need to update anything here
|
||||
}
|
||||
}
|
||||
|
||||
class DraggableWindowNSView: NSView {
|
||||
override func mouseDown(with event: NSEvent) {
|
||||
guard let window = self.window else { return }
|
||||
window.performDrag(with: event)
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,6 @@ extension NSWindow {
|
||||
return CGWindowID(windowNumber)
|
||||
}
|
||||
|
||||
/// True if this is the first window in the tab group.
|
||||
var isFirstWindowInTabGroup: Bool {
|
||||
guard let firstWindow = tabGroup?.windows.first else { return true }
|
||||
return firstWindow === self
|
||||
}
|
||||
|
||||
/// Adjusts the window frame if necessary to ensure the window remains visible on screen.
|
||||
/// This constrains both the size (to not exceed the screen) and the origin (to keep the window on screen).
|
||||
func constrainToScreen() {
|
||||
@@ -36,3 +30,53 @@ extension NSWindow {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Native Tabbing
|
||||
|
||||
extension NSWindow {
|
||||
/// True if this is the first window in the tab group.
|
||||
var isFirstWindowInTabGroup: Bool {
|
||||
guard let firstWindow = tabGroup?.windows.first else { return true }
|
||||
return firstWindow === self
|
||||
}
|
||||
}
|
||||
|
||||
/// Native tabbing private API usage. :(
|
||||
extension NSWindow {
|
||||
var titlebarView: NSView? {
|
||||
// In normal window, `NSTabBar` typically appears as a subview of `NSTitlebarView` within `NSThemeFrame`.
|
||||
// In fullscreen, the system creates a dedicated fullscreen window and the view hierarchy changes;
|
||||
// in that case, the `titlebarView` is only accessible via a reference on `NSThemeFrame`.
|
||||
// ref: https://github.com/mozilla-firefox/firefox/blob/054e2b072785984455b3b59acad9444ba1eeffb4/widget/cocoa/nsCocoaWindow.mm#L7205
|
||||
guard let themeFrameView = contentView?.rootView else { return nil }
|
||||
guard themeFrameView.responds(to: Selector(("titlebarView"))) else { return nil }
|
||||
return themeFrameView.value(forKey: "titlebarView") as? NSView
|
||||
}
|
||||
|
||||
/// Returns the [private] NSTabBar view, if it exists.
|
||||
var tabBarView: NSView? {
|
||||
titlebarView?.firstDescendant(withClassName: "NSTabBar")
|
||||
}
|
||||
|
||||
/// Returns the index of the tab button at the given screen point, if any.
|
||||
func tabIndex(atScreenPoint screenPoint: NSPoint) -> Int? {
|
||||
guard let tabBarView else { return nil }
|
||||
let locationInWindow = convertPoint(fromScreen: screenPoint)
|
||||
let locationInTabBar = tabBarView.convert(locationInWindow, from: nil)
|
||||
guard tabBarView.bounds.contains(locationInTabBar) else { return nil }
|
||||
|
||||
// Find all tab buttons and sort by x position to get visual order.
|
||||
// The view hierarchy order doesn't match the visual tab order.
|
||||
let tabItemViews = tabBarView.descendants(withClassName: "NSTabButton")
|
||||
.sorted { $0.frame.origin.x < $1.frame.origin.x }
|
||||
|
||||
for (index, tabItemView) in tabItemViews.enumerated() {
|
||||
let locationInTab = tabItemView.convert(locationInWindow, from: nil)
|
||||
if tabItemView.bounds.contains(locationInTab) {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
const std = @import("std");
|
||||
const NativeTargetInfo = std.zig.system.NativeTargetInfo;
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const module = b.addModule("cimgui", .{
|
||||
.root_source_file = b.path("main.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const imgui_ = b.lazyDependency("imgui", .{});
|
||||
const lib = b.addLibrary(.{
|
||||
.name = "cimgui",
|
||||
.root_module = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
.linkage = .static,
|
||||
});
|
||||
lib.linkLibC();
|
||||
lib.linkLibCpp();
|
||||
if (target.result.os.tag == .windows) {
|
||||
lib.linkSystemLibrary("imm32");
|
||||
}
|
||||
|
||||
// For dynamic linking, we prefer dynamic linking and to search by
|
||||
// mode first. Mode first will search all paths for a dynamic library
|
||||
// before falling back to static.
|
||||
const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
|
||||
.preferred_link_mode = .dynamic,
|
||||
.search_strategy = .mode_first,
|
||||
};
|
||||
|
||||
if (b.systemIntegrationOption("freetype", .{})) {
|
||||
lib.linkSystemLibrary2("freetype2", dynamic_link_opts);
|
||||
} else {
|
||||
const freetype = b.dependency("freetype", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.@"enable-libpng" = true,
|
||||
});
|
||||
lib.linkLibrary(freetype.artifact("freetype"));
|
||||
|
||||
if (freetype.builder.lazyDependency(
|
||||
"freetype",
|
||||
.{},
|
||||
)) |freetype_dep| {
|
||||
module.addIncludePath(freetype_dep.path("include"));
|
||||
}
|
||||
}
|
||||
|
||||
if (imgui_) |imgui| lib.addIncludePath(imgui.path(""));
|
||||
module.addIncludePath(b.path("vendor"));
|
||||
|
||||
var flags: std.ArrayList([]const u8) = .empty;
|
||||
defer flags.deinit(b.allocator);
|
||||
try flags.appendSlice(b.allocator, &.{
|
||||
"-DCIMGUI_FREETYPE=1",
|
||||
"-DIMGUI_USE_WCHAR32=1",
|
||||
"-DIMGUI_DISABLE_OBSOLETE_FUNCTIONS=1",
|
||||
});
|
||||
if (target.result.os.tag == .windows) {
|
||||
try flags.appendSlice(b.allocator, &.{
|
||||
"-DIMGUI_IMPL_API=extern\t\"C\"\t__declspec(dllexport)",
|
||||
});
|
||||
} else {
|
||||
try flags.appendSlice(b.allocator, &.{
|
||||
"-DIMGUI_IMPL_API=extern\t\"C\"",
|
||||
});
|
||||
}
|
||||
|
||||
if (target.result.os.tag == .freebsd) {
|
||||
try flags.append(b.allocator, "-fPIC");
|
||||
}
|
||||
|
||||
if (imgui_) |imgui| {
|
||||
lib.addCSourceFile(.{ .file = b.path("vendor/cimgui.cpp"), .flags = flags.items });
|
||||
lib.addCSourceFile(.{ .file = imgui.path("imgui.cpp"), .flags = flags.items });
|
||||
lib.addCSourceFile(.{ .file = imgui.path("imgui_draw.cpp"), .flags = flags.items });
|
||||
lib.addCSourceFile(.{ .file = imgui.path("imgui_demo.cpp"), .flags = flags.items });
|
||||
lib.addCSourceFile(.{ .file = imgui.path("imgui_widgets.cpp"), .flags = flags.items });
|
||||
lib.addCSourceFile(.{ .file = imgui.path("imgui_tables.cpp"), .flags = flags.items });
|
||||
lib.addCSourceFile(.{ .file = imgui.path("misc/freetype/imgui_freetype.cpp"), .flags = flags.items });
|
||||
lib.addCSourceFile(.{
|
||||
.file = imgui.path("backends/imgui_impl_opengl3.cpp"),
|
||||
.flags = flags.items,
|
||||
});
|
||||
|
||||
if (target.result.os.tag.isDarwin()) {
|
||||
if (!target.query.isNative()) {
|
||||
try @import("apple_sdk").addPaths(b, lib);
|
||||
}
|
||||
lib.addCSourceFile(.{
|
||||
.file = imgui.path("backends/imgui_impl_metal.mm"),
|
||||
.flags = flags.items,
|
||||
});
|
||||
if (target.result.os.tag == .macos) {
|
||||
lib.addCSourceFile(.{
|
||||
.file = imgui.path("backends/imgui_impl_osx.mm"),
|
||||
.flags = flags.items,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lib.installHeadersDirectory(
|
||||
b.path("vendor"),
|
||||
"",
|
||||
.{ .include_extensions = &.{".h"} },
|
||||
);
|
||||
|
||||
b.installArtifact(lib);
|
||||
|
||||
const test_exe = b.addTest(.{
|
||||
.name = "test",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("main.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
});
|
||||
test_exe.linkLibrary(lib);
|
||||
const tests_run = b.addRunArtifact(test_exe);
|
||||
const test_step = b.step("test", "Run tests");
|
||||
test_step.dependOn(&tests_run.step);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
.{
|
||||
.name = .cimgui,
|
||||
.version = "1.90.6", // -docking branch
|
||||
.fingerprint = 0x49726f5f8acbc90d,
|
||||
.paths = .{""},
|
||||
.dependencies = .{
|
||||
// This should be kept in sync with the submodule in the cimgui source
|
||||
// code in ./vendor/ to be safe that they're compatible.
|
||||
.imgui = .{
|
||||
// ocornut/imgui
|
||||
.url = "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz",
|
||||
.hash = "N-V-__8AAH0GaQC8a52s6vfIxg88OZgFgEW6DFxfSK4lX_l3",
|
||||
.lazy = true,
|
||||
},
|
||||
|
||||
.apple_sdk = .{ .path = "../apple-sdk" },
|
||||
.freetype = .{ .path = "../freetype" },
|
||||
},
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
pub const c = @cImport({
|
||||
@cDefine("CIMGUI_DEFINE_ENUMS_AND_STRUCTS", "1");
|
||||
@cInclude("cimgui.h");
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
pub const c = @import("c.zig").c;
|
||||
|
||||
// OpenGL
|
||||
pub extern fn ImGui_ImplOpenGL3_Init(?[*:0]const u8) callconv(.c) bool;
|
||||
pub extern fn ImGui_ImplOpenGL3_Shutdown() callconv(.c) void;
|
||||
pub extern fn ImGui_ImplOpenGL3_NewFrame() callconv(.c) void;
|
||||
pub extern fn ImGui_ImplOpenGL3_RenderDrawData(*c.ImDrawData) callconv(.c) void;
|
||||
|
||||
// Metal
|
||||
pub extern fn ImGui_ImplMetal_Init(*anyopaque) callconv(.c) bool;
|
||||
pub extern fn ImGui_ImplMetal_Shutdown() callconv(.c) void;
|
||||
pub extern fn ImGui_ImplMetal_NewFrame(*anyopaque) callconv(.c) void;
|
||||
pub extern fn ImGui_ImplMetal_RenderDrawData(*c.ImDrawData, *anyopaque, *anyopaque) callconv(.c) void;
|
||||
|
||||
// OSX
|
||||
pub extern fn ImGui_ImplOSX_Init(*anyopaque) callconv(.c) bool;
|
||||
pub extern fn ImGui_ImplOSX_Shutdown() callconv(.c) void;
|
||||
pub extern fn ImGui_ImplOSX_NewFrame(*anyopaque) callconv(.c) void;
|
||||
|
||||
test {}
|
||||
5943
pkg/cimgui/vendor/cimgui.cpp
vendored
5943
pkg/cimgui/vendor/cimgui.cpp
vendored
File diff suppressed because it is too large
Load Diff
6554
pkg/cimgui/vendor/cimgui.h
vendored
6554
pkg/cimgui/vendor/cimgui.h
vendored
File diff suppressed because it is too large
Load Diff
199
pkg/dcimgui/build.zig
Normal file
199
pkg/dcimgui/build.zig
Normal file
@@ -0,0 +1,199 @@
|
||||
const std = @import("std");
|
||||
const NativeTargetInfo = std.zig.system.NativeTargetInfo;
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const freetype = b.option(bool, "freetype", "Use Freetype") orelse false;
|
||||
const backend_opengl3 = b.option(bool, "backend-opengl3", "OpenGL3 backend") orelse false;
|
||||
const backend_metal = b.option(bool, "backend-metal", "Metal backend") orelse false;
|
||||
const backend_osx = b.option(bool, "backend-osx", "OSX backend") orelse false;
|
||||
|
||||
// Build options
|
||||
const options = b.addOptions();
|
||||
options.addOption(bool, "freetype", freetype);
|
||||
options.addOption(bool, "backend_opengl3", backend_opengl3);
|
||||
options.addOption(bool, "backend_metal", backend_metal);
|
||||
options.addOption(bool, "backend_osx", backend_osx);
|
||||
|
||||
// Main static lib
|
||||
const lib = b.addLibrary(.{
|
||||
.name = "dcimgui",
|
||||
.root_module = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
.linkage = .static,
|
||||
});
|
||||
lib.linkLibC();
|
||||
lib.linkLibCpp();
|
||||
b.installArtifact(lib);
|
||||
|
||||
// Zig module
|
||||
const mod = b.addModule("dcimgui", .{
|
||||
.root_source_file = b.path("main.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
mod.addOptions("build_options", options);
|
||||
mod.linkLibrary(lib);
|
||||
|
||||
// We need to add proper Apple SDKs to find stdlib headers
|
||||
if (target.result.os.tag.isDarwin()) {
|
||||
if (!target.query.isNative()) {
|
||||
try @import("apple_sdk").addPaths(b, lib);
|
||||
}
|
||||
}
|
||||
|
||||
// Flags for C compilation, common to all.
|
||||
var flags: std.ArrayList([]const u8) = .empty;
|
||||
defer flags.deinit(b.allocator);
|
||||
try flags.appendSlice(b.allocator, &.{
|
||||
"-DIMGUI_USE_WCHAR32=1",
|
||||
"-DIMGUI_DISABLE_OBSOLETE_FUNCTIONS=1",
|
||||
});
|
||||
if (freetype) try flags.appendSlice(b.allocator, &.{
|
||||
"-DIMGUI_ENABLE_FREETYPE=1",
|
||||
});
|
||||
if (target.result.os.tag == .windows) {
|
||||
try flags.appendSlice(b.allocator, &.{
|
||||
"-DIMGUI_IMPL_API=extern\t\"C\"\t__declspec(dllexport)",
|
||||
});
|
||||
} else {
|
||||
try flags.appendSlice(b.allocator, &.{
|
||||
"-DIMGUI_IMPL_API=extern\t\"C\"",
|
||||
});
|
||||
}
|
||||
if (target.result.os.tag == .freebsd) {
|
||||
try flags.append(b.allocator, "-fPIC");
|
||||
}
|
||||
|
||||
// Add the core Dear Imgui source files
|
||||
if (b.lazyDependency("imgui", .{})) |upstream| {
|
||||
lib.addIncludePath(upstream.path(""));
|
||||
lib.addCSourceFiles(.{
|
||||
.root = upstream.path(""),
|
||||
.files = &.{
|
||||
"imgui_demo.cpp",
|
||||
"imgui_draw.cpp",
|
||||
"imgui_tables.cpp",
|
||||
"imgui_widgets.cpp",
|
||||
"imgui.cpp",
|
||||
},
|
||||
.flags = flags.items,
|
||||
});
|
||||
|
||||
lib.installHeadersDirectory(
|
||||
upstream.path(""),
|
||||
"",
|
||||
.{ .include_extensions = &.{".h"} },
|
||||
);
|
||||
|
||||
if (freetype) {
|
||||
lib.addCSourceFile(.{
|
||||
.file = upstream.path("misc/freetype/imgui_freetype.cpp"),
|
||||
.flags = flags.items,
|
||||
});
|
||||
|
||||
if (b.systemIntegrationOption("freetype", .{})) {
|
||||
lib.linkSystemLibrary2("freetype2", dynamic_link_opts);
|
||||
} else {
|
||||
const freetype_dep = b.dependency("freetype", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.@"enable-libpng" = true,
|
||||
});
|
||||
lib.linkLibrary(freetype_dep.artifact("freetype"));
|
||||
if (freetype_dep.builder.lazyDependency(
|
||||
"freetype",
|
||||
.{},
|
||||
)) |freetype_upstream| {
|
||||
mod.addIncludePath(freetype_upstream.path("include"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (backend_metal) {
|
||||
lib.addCSourceFiles(.{
|
||||
.root = upstream.path("backends"),
|
||||
.files = &.{"imgui_impl_metal.mm"},
|
||||
.flags = flags.items,
|
||||
});
|
||||
lib.installHeadersDirectory(
|
||||
upstream.path("backends"),
|
||||
"",
|
||||
.{ .include_extensions = &.{"imgui_impl_metal.h"} },
|
||||
);
|
||||
}
|
||||
if (backend_osx) {
|
||||
lib.addCSourceFiles(.{
|
||||
.root = upstream.path("backends"),
|
||||
.files = &.{"imgui_impl_osx.mm"},
|
||||
.flags = flags.items,
|
||||
});
|
||||
lib.installHeadersDirectory(
|
||||
upstream.path("backends"),
|
||||
"",
|
||||
.{ .include_extensions = &.{"imgui_impl_osx.h"} },
|
||||
);
|
||||
}
|
||||
if (backend_opengl3) {
|
||||
lib.addCSourceFiles(.{
|
||||
.root = upstream.path("backends"),
|
||||
.files = &.{"imgui_impl_opengl3.cpp"},
|
||||
.flags = flags.items,
|
||||
});
|
||||
lib.installHeadersDirectory(
|
||||
upstream.path("backends"),
|
||||
"",
|
||||
.{ .include_extensions = &.{"imgui_impl_opengl3.h"} },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the C bindings
|
||||
if (b.lazyDependency("bindings", .{})) |upstream| {
|
||||
lib.addIncludePath(upstream.path(""));
|
||||
lib.addCSourceFiles(.{
|
||||
.root = upstream.path(""),
|
||||
.files = &.{
|
||||
"dcimgui.cpp",
|
||||
"dcimgui_internal.cpp",
|
||||
},
|
||||
.flags = flags.items,
|
||||
});
|
||||
lib.addCSourceFiles(.{
|
||||
.root = b.path(""),
|
||||
.files = &.{"ext.cpp"},
|
||||
.flags = flags.items,
|
||||
});
|
||||
|
||||
lib.installHeadersDirectory(
|
||||
upstream.path(""),
|
||||
"",
|
||||
.{ .include_extensions = &.{".h"} },
|
||||
);
|
||||
}
|
||||
|
||||
const test_exe = b.addTest(.{
|
||||
.name = "test",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("main.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
});
|
||||
test_exe.root_module.addOptions("build_options", options);
|
||||
test_exe.linkLibrary(lib);
|
||||
const tests_run = b.addRunArtifact(test_exe);
|
||||
const test_step = b.step("test", "Run tests");
|
||||
test_step.dependOn(&tests_run.step);
|
||||
}
|
||||
|
||||
// For dynamic linking, we prefer dynamic linking and to search by
|
||||
// mode first. Mode first will search all paths for a dynamic library
|
||||
// before falling back to static.
|
||||
const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
|
||||
.preferred_link_mode = .dynamic,
|
||||
.search_strategy = .mode_first,
|
||||
};
|
||||
26
pkg/dcimgui/build.zig.zon
Normal file
26
pkg/dcimgui/build.zig.zon
Normal file
@@ -0,0 +1,26 @@
|
||||
.{
|
||||
.name = .dcimgui,
|
||||
.version = "1.92.5", // -docking branch
|
||||
.fingerprint = 0x1a25797442c6324f,
|
||||
.paths = .{""},
|
||||
.dependencies = .{
|
||||
// The bindings and imgui versions below must match exactly.
|
||||
|
||||
.bindings = .{
|
||||
// https://github.com/dearimgui/dear_bindings
|
||||
.url = "https://deps.files.ghostty.org/DearBindings_v0.17_ImGui_v1.92.5-docking.tar.gz",
|
||||
.hash = "N-V-__8AANT61wB--nJ95Gj_ctmzAtcjloZ__hRqNw5lC1Kr",
|
||||
.lazy = true,
|
||||
},
|
||||
|
||||
.imgui = .{
|
||||
// https://github.com/ocornut/imgui
|
||||
.url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.92.5-docking.tar.gz",
|
||||
.hash = "N-V-__8AAEbOfQBnvcFcCX2W5z7tDaN8vaNZGamEQtNOe0UI",
|
||||
.lazy = true,
|
||||
},
|
||||
|
||||
.apple_sdk = .{ .path = "../apple-sdk" },
|
||||
.freetype = .{ .path = "../freetype" },
|
||||
},
|
||||
}
|
||||
30
pkg/dcimgui/ext.cpp
Normal file
30
pkg/dcimgui/ext.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "imgui.h"
|
||||
|
||||
// This file contains custom extensions for functionality that isn't
|
||||
// properly supported by Dear Bindings yet. Namely:
|
||||
// https://github.com/dearimgui/dear_bindings/issues/55
|
||||
|
||||
// Wrap this in a namespace to keep it separate from the C++ API
|
||||
namespace cimgui
|
||||
{
|
||||
#include "dcimgui.h"
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
CIMGUI_API void ImFontConfig_ImFontConfig(cimgui::ImFontConfig* self)
|
||||
{
|
||||
static_assert(sizeof(cimgui::ImFontConfig) == sizeof(::ImFontConfig), "ImFontConfig size mismatch");
|
||||
static_assert(alignof(cimgui::ImFontConfig) == alignof(::ImFontConfig), "ImFontConfig alignment mismatch");
|
||||
::ImFontConfig defaults;
|
||||
*reinterpret_cast<::ImFontConfig*>(self) = defaults;
|
||||
}
|
||||
|
||||
CIMGUI_API void ImGuiStyle_ImGuiStyle(cimgui::ImGuiStyle* self)
|
||||
{
|
||||
static_assert(sizeof(cimgui::ImGuiStyle) == sizeof(::ImGuiStyle), "ImGuiStyle size mismatch");
|
||||
static_assert(alignof(cimgui::ImGuiStyle) == alignof(::ImGuiStyle), "ImGuiStyle alignment mismatch");
|
||||
::ImGuiStyle defaults;
|
||||
*reinterpret_cast<::ImGuiStyle*>(self) = defaults;
|
||||
}
|
||||
}
|
||||
43
pkg/dcimgui/main.zig
Normal file
43
pkg/dcimgui/main.zig
Normal file
@@ -0,0 +1,43 @@
|
||||
pub const build_options = @import("build_options");
|
||||
|
||||
pub const c = @cImport({
|
||||
// This is set during the build so it also has to be set
|
||||
// during import time to get the right types. Without this
|
||||
// you get stack size mismatches on some structs.
|
||||
@cDefine("IMGUI_USE_WCHAR32", "1");
|
||||
@cInclude("dcimgui.h");
|
||||
});
|
||||
|
||||
// OpenGL3 backend
|
||||
pub extern fn ImGui_ImplOpenGL3_Init(glsl_version: ?[*:0]const u8) callconv(.c) bool;
|
||||
pub extern fn ImGui_ImplOpenGL3_Shutdown() callconv(.c) void;
|
||||
pub extern fn ImGui_ImplOpenGL3_NewFrame() callconv(.c) void;
|
||||
pub extern fn ImGui_ImplOpenGL3_RenderDrawData(draw_data: *c.ImDrawData) callconv(.c) void;
|
||||
|
||||
// Metal backend
|
||||
pub extern fn ImGui_ImplMetal_Init(device: *anyopaque) callconv(.c) bool;
|
||||
pub extern fn ImGui_ImplMetal_Shutdown() callconv(.c) void;
|
||||
pub extern fn ImGui_ImplMetal_NewFrame(render_pass_descriptor: *anyopaque) callconv(.c) void;
|
||||
pub extern fn ImGui_ImplMetal_RenderDrawData(draw_data: *c.ImDrawData, command_buffer: *anyopaque, command_encoder: *anyopaque) callconv(.c) void;
|
||||
|
||||
// OSX
|
||||
pub extern fn ImGui_ImplOSX_Init(*anyopaque) callconv(.c) bool;
|
||||
pub extern fn ImGui_ImplOSX_Shutdown() callconv(.c) void;
|
||||
pub extern fn ImGui_ImplOSX_NewFrame(*anyopaque) callconv(.c) void;
|
||||
|
||||
// Internal API functions from dcimgui_internal.h
|
||||
// We declare these manually because the internal header contains bitfields
|
||||
// that Zig's cImport cannot translate.
|
||||
pub extern fn ImGui_DockBuilderDockWindow(window_name: [*:0]const u8, node_id: c.ImGuiID) callconv(.c) void;
|
||||
pub extern fn ImGui_DockBuilderSplitNode(node_id: c.ImGuiID, split_dir: c.ImGuiDir, size_ratio_for_node_at_dir: f32, out_id_at_dir: *c.ImGuiID, out_id_at_opposite_dir: *c.ImGuiID) callconv(.c) c.ImGuiID;
|
||||
pub extern fn ImGui_DockBuilderFinish(node_id: c.ImGuiID) callconv(.c) void;
|
||||
|
||||
// Extension functions from ext.cpp
|
||||
pub const ext = struct {
|
||||
pub extern fn ImFontConfig_ImFontConfig(self: *c.ImFontConfig) callconv(.c) void;
|
||||
pub extern fn ImGuiStyle_ImGuiStyle(self: *c.ImGuiStyle) callconv(.c) void;
|
||||
};
|
||||
|
||||
test {
|
||||
_ = c;
|
||||
}
|
||||
@@ -947,7 +947,7 @@ pub const Surface = struct {
|
||||
/// Inspector is the state required for the terminal inspector. A terminal
|
||||
/// inspector is 1:1 with a Surface.
|
||||
pub const Inspector = struct {
|
||||
const cimgui = @import("cimgui");
|
||||
const cimgui = @import("dcimgui");
|
||||
|
||||
surface: *Surface,
|
||||
ig_ctx: *cimgui.c.ImGuiContext,
|
||||
@@ -968,10 +968,10 @@ pub const Inspector = struct {
|
||||
};
|
||||
|
||||
pub fn init(surface: *Surface) !Inspector {
|
||||
const ig_ctx = cimgui.c.igCreateContext(null) orelse return error.OutOfMemory;
|
||||
errdefer cimgui.c.igDestroyContext(ig_ctx);
|
||||
cimgui.c.igSetCurrentContext(ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const ig_ctx = cimgui.c.ImGui_CreateContext(null) orelse return error.OutOfMemory;
|
||||
errdefer cimgui.c.ImGui_DestroyContext(ig_ctx);
|
||||
cimgui.c.ImGui_SetCurrentContext(ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
io.BackendPlatformName = "ghostty_embedded";
|
||||
|
||||
// Setup our core inspector
|
||||
@@ -988,9 +988,9 @@ pub const Inspector = struct {
|
||||
|
||||
pub fn deinit(self: *Inspector) void {
|
||||
self.surface.core_surface.deactivateInspector();
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
if (self.backend) |v| v.deinit();
|
||||
cimgui.c.igDestroyContext(self.ig_ctx);
|
||||
cimgui.c.ImGui_DestroyContext(self.ig_ctx);
|
||||
}
|
||||
|
||||
/// Queue a render for the next frame.
|
||||
@@ -1001,7 +1001,7 @@ pub const Inspector = struct {
|
||||
/// Initialize the inspector for a metal backend.
|
||||
pub fn initMetal(self: *Inspector, device: objc.Object) bool {
|
||||
defer device.msgSend(void, objc.sel("release"), .{});
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
|
||||
if (self.backend) |v| {
|
||||
v.deinit();
|
||||
@@ -1036,7 +1036,7 @@ pub const Inspector = struct {
|
||||
for (0..2) |_| {
|
||||
cimgui.ImGui_ImplMetal_NewFrame(desc.value);
|
||||
try self.newFrame();
|
||||
cimgui.c.igNewFrame();
|
||||
cimgui.c.ImGui_NewFrame();
|
||||
|
||||
// Build our UI
|
||||
render: {
|
||||
@@ -1046,7 +1046,7 @@ pub const Inspector = struct {
|
||||
}
|
||||
|
||||
// Render
|
||||
cimgui.c.igRender();
|
||||
cimgui.c.ImGui_Render();
|
||||
}
|
||||
|
||||
// MTLRenderCommandEncoder
|
||||
@@ -1057,7 +1057,7 @@ pub const Inspector = struct {
|
||||
);
|
||||
defer encoder.msgSend(void, objc.sel("endEncoding"), .{});
|
||||
cimgui.ImGui_ImplMetal_RenderDrawData(
|
||||
cimgui.c.igGetDrawData(),
|
||||
cimgui.c.ImGui_GetDrawData(),
|
||||
command_buffer.value,
|
||||
encoder.value,
|
||||
);
|
||||
@@ -1065,22 +1065,24 @@ pub const Inspector = struct {
|
||||
|
||||
pub fn updateContentScale(self: *Inspector, x: f64, y: f64) void {
|
||||
_ = y;
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
|
||||
// Cache our scale because we use it for cursor position calculations.
|
||||
self.content_scale = x;
|
||||
|
||||
// Setup a new style and scale it appropriately.
|
||||
const style = cimgui.c.ImGuiStyle_ImGuiStyle();
|
||||
defer cimgui.c.ImGuiStyle_destroy(style);
|
||||
cimgui.c.ImGuiStyle_ScaleAllSizes(style, @floatCast(x));
|
||||
const active_style = cimgui.c.igGetStyle();
|
||||
active_style.* = style.*;
|
||||
// Setup a new style and scale it appropriately. We must use the
|
||||
// ImGuiStyle constructor to get proper default values (e.g.,
|
||||
// CurveTessellationTol) rather than zero-initialized values.
|
||||
var style: cimgui.c.ImGuiStyle = undefined;
|
||||
cimgui.ext.ImGuiStyle_ImGuiStyle(&style);
|
||||
cimgui.c.ImGuiStyle_ScaleAllSizes(&style, @floatCast(x));
|
||||
const active_style = cimgui.c.ImGui_GetStyle();
|
||||
active_style.* = style;
|
||||
}
|
||||
|
||||
pub fn updateSize(self: *Inspector, width: u32, height: u32) void {
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
io.DisplaySize = .{ .x = @floatFromInt(width), .y = @floatFromInt(height) };
|
||||
}
|
||||
|
||||
@@ -1093,8 +1095,8 @@ pub const Inspector = struct {
|
||||
_ = mods;
|
||||
|
||||
self.queueRender();
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
|
||||
const imgui_button = switch (button) {
|
||||
.left => cimgui.c.ImGuiMouseButton_Left,
|
||||
@@ -1115,8 +1117,8 @@ pub const Inspector = struct {
|
||||
_ = mods;
|
||||
|
||||
self.queueRender();
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
cimgui.c.ImGuiIO_AddMouseWheelEvent(
|
||||
io,
|
||||
@floatCast(xoff),
|
||||
@@ -1126,8 +1128,8 @@ pub const Inspector = struct {
|
||||
|
||||
pub fn cursorPosCallback(self: *Inspector, x: f64, y: f64) void {
|
||||
self.queueRender();
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
cimgui.c.ImGuiIO_AddMousePosEvent(
|
||||
io,
|
||||
@floatCast(x * self.content_scale),
|
||||
@@ -1137,15 +1139,15 @@ pub const Inspector = struct {
|
||||
|
||||
pub fn focusCallback(self: *Inspector, focused: bool) void {
|
||||
self.queueRender();
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
cimgui.c.ImGuiIO_AddFocusEvent(io, focused);
|
||||
}
|
||||
|
||||
pub fn textCallback(self: *Inspector, text: [:0]const u8) void {
|
||||
self.queueRender();
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
cimgui.c.ImGuiIO_AddInputCharactersUTF8(io, text.ptr);
|
||||
}
|
||||
|
||||
@@ -1156,8 +1158,8 @@ pub const Inspector = struct {
|
||||
mods: input.Mods,
|
||||
) !void {
|
||||
self.queueRender();
|
||||
cimgui.c.igSetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
cimgui.c.ImGui_SetCurrentContext(self.ig_ctx);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
|
||||
// Update all our modifiers
|
||||
cimgui.c.ImGuiIO_AddKeyEvent(io, cimgui.c.ImGuiKey_LeftShift, mods.shift);
|
||||
@@ -1176,7 +1178,7 @@ pub const Inspector = struct {
|
||||
}
|
||||
|
||||
fn newFrame(self: *Inspector) !void {
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
|
||||
// Determine our delta time
|
||||
const now = try std.time.Instant.now();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const assert = @import("../../../quirks.zig").inlineAssert;
|
||||
|
||||
const cimgui = @import("cimgui");
|
||||
const cimgui = @import("dcimgui");
|
||||
const gl = @import("opengl");
|
||||
const adw = @import("adw");
|
||||
const gdk = @import("gdk");
|
||||
@@ -126,7 +126,7 @@ pub const ImguiWidget = extern struct {
|
||||
log.warn("Dear ImGui context not initialized", .{});
|
||||
return error.ContextNotInitialized;
|
||||
};
|
||||
cimgui.c.igSetCurrentContext(ig_context);
|
||||
cimgui.c.ImGui_SetCurrentContext(ig_context);
|
||||
}
|
||||
|
||||
/// Initialize the frame. Expects that the context is already current.
|
||||
@@ -137,7 +137,7 @@ pub const ImguiWidget = extern struct {
|
||||
|
||||
const priv = self.private();
|
||||
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
|
||||
// Determine our delta time
|
||||
const now = std.time.Instant.now() catch unreachable;
|
||||
@@ -163,7 +163,7 @@ pub const ImguiWidget = extern struct {
|
||||
|
||||
self.setCurrentContext() catch return false;
|
||||
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
|
||||
const mods = key.translateMods(gtk_mods);
|
||||
cimgui.c.ImGuiIO_AddKeyEvent(io, cimgui.c.ImGuiKey_LeftShift, mods.shift);
|
||||
@@ -219,14 +219,14 @@ pub const ImguiWidget = extern struct {
|
||||
return;
|
||||
}
|
||||
|
||||
priv.ig_context = cimgui.c.igCreateContext(null) orelse {
|
||||
priv.ig_context = cimgui.c.ImGui_CreateContext(null) orelse {
|
||||
log.warn("unable to initialize Dear ImGui context", .{});
|
||||
return;
|
||||
};
|
||||
self.setCurrentContext() catch return;
|
||||
|
||||
// Setup some basic config
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
io.BackendPlatformName = "ghostty_gtk";
|
||||
|
||||
// Realize means that our OpenGL context is ready, so we can now
|
||||
@@ -247,7 +247,7 @@ pub const ImguiWidget = extern struct {
|
||||
/// Handle a request to resize the GLArea
|
||||
fn glAreaResize(area: *gtk.GLArea, width: c_int, height: c_int, self: *Self) callconv(.c) void {
|
||||
self.setCurrentContext() catch return;
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
const scale_factor = area.as(gtk.Widget).getScaleFactor();
|
||||
|
||||
// Our display size is always unscaled. We'll do the scaling in the
|
||||
@@ -255,12 +255,14 @@ pub const ImguiWidget = extern struct {
|
||||
io.DisplaySize = .{ .x = @floatFromInt(width), .y = @floatFromInt(height) };
|
||||
io.DisplayFramebufferScale = .{ .x = 1, .y = 1 };
|
||||
|
||||
// Setup a new style and scale it appropriately.
|
||||
const style = cimgui.c.ImGuiStyle_ImGuiStyle();
|
||||
defer cimgui.c.ImGuiStyle_destroy(style);
|
||||
cimgui.c.ImGuiStyle_ScaleAllSizes(style, @floatFromInt(scale_factor));
|
||||
const active_style = cimgui.c.igGetStyle();
|
||||
active_style.* = style.*;
|
||||
// Setup a new style and scale it appropriately. We must use the
|
||||
// ImGuiStyle constructor to get proper default values (e.g.,
|
||||
// CurveTessellationTol) rather than zero-initialized values.
|
||||
var style: cimgui.c.ImGuiStyle = undefined;
|
||||
cimgui.ext.ImGuiStyle_ImGuiStyle(&style);
|
||||
cimgui.c.ImGuiStyle_ScaleAllSizes(&style, @floatFromInt(scale_factor));
|
||||
const active_style = cimgui.c.ImGui_GetStyle();
|
||||
active_style.* = style;
|
||||
}
|
||||
|
||||
/// Handle a request to render the contents of our GLArea
|
||||
@@ -273,33 +275,33 @@ pub const ImguiWidget = extern struct {
|
||||
for (0..2) |_| {
|
||||
cimgui.ImGui_ImplOpenGL3_NewFrame();
|
||||
self.newFrame();
|
||||
cimgui.c.igNewFrame();
|
||||
cimgui.c.ImGui_NewFrame();
|
||||
|
||||
// Call the virtual method to draw the UI.
|
||||
self.render();
|
||||
|
||||
// Render
|
||||
cimgui.c.igRender();
|
||||
cimgui.c.ImGui_Render();
|
||||
}
|
||||
|
||||
// OpenGL final render
|
||||
gl.clearColor(0x28 / 0xFF, 0x2C / 0xFF, 0x34 / 0xFF, 1.0);
|
||||
gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
|
||||
cimgui.ImGui_ImplOpenGL3_RenderDrawData(cimgui.c.igGetDrawData());
|
||||
cimgui.ImGui_ImplOpenGL3_RenderDrawData(cimgui.c.ImGui_GetDrawData());
|
||||
|
||||
return @intFromBool(true);
|
||||
}
|
||||
|
||||
fn ecFocusEnter(_: *gtk.EventControllerFocus, self: *Self) callconv(.c) void {
|
||||
self.setCurrentContext() catch return;
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
cimgui.c.ImGuiIO_AddFocusEvent(io, true);
|
||||
self.queueRender();
|
||||
}
|
||||
|
||||
fn ecFocusLeave(_: *gtk.EventControllerFocus, self: *Self) callconv(.c) void {
|
||||
self.setCurrentContext() catch return;
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
cimgui.c.ImGuiIO_AddFocusEvent(io, false);
|
||||
self.queueRender();
|
||||
}
|
||||
@@ -345,7 +347,7 @@ pub const ImguiWidget = extern struct {
|
||||
) callconv(.c) void {
|
||||
self.queueRender();
|
||||
self.setCurrentContext() catch return;
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
const gdk_button = gesture.as(gtk.GestureSingle).getCurrentButton();
|
||||
if (translateMouseButton(gdk_button)) |button| {
|
||||
cimgui.c.ImGuiIO_AddMouseButtonEvent(io, button, true);
|
||||
@@ -361,7 +363,7 @@ pub const ImguiWidget = extern struct {
|
||||
) callconv(.c) void {
|
||||
self.queueRender();
|
||||
self.setCurrentContext() catch return;
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
const gdk_button = gesture.as(gtk.GestureSingle).getCurrentButton();
|
||||
if (translateMouseButton(gdk_button)) |button| {
|
||||
cimgui.c.ImGuiIO_AddMouseButtonEvent(io, button, false);
|
||||
@@ -376,7 +378,7 @@ pub const ImguiWidget = extern struct {
|
||||
) callconv(.c) void {
|
||||
self.queueRender();
|
||||
self.setCurrentContext() catch return;
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
const scale_factor = self.getScaleFactor();
|
||||
cimgui.c.ImGuiIO_AddMousePosEvent(
|
||||
io,
|
||||
@@ -393,7 +395,7 @@ pub const ImguiWidget = extern struct {
|
||||
) callconv(.c) c_int {
|
||||
self.queueRender();
|
||||
self.setCurrentContext() catch return @intFromBool(false);
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
cimgui.c.ImGuiIO_AddMouseWheelEvent(
|
||||
io,
|
||||
@floatCast(x),
|
||||
@@ -409,7 +411,7 @@ pub const ImguiWidget = extern struct {
|
||||
) callconv(.c) void {
|
||||
self.queueRender();
|
||||
self.setCurrentContext() catch return;
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.igGetIO();
|
||||
const io: *cimgui.c.ImGuiIO = cimgui.c.ImGui_GetIO();
|
||||
cimgui.c.ImGuiIO_AddInputCharactersUTF8(io, bytes);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,29 +135,28 @@ pub fn add(
|
||||
// Every exe needs the terminal options
|
||||
self.config.terminalOptions().add(b, step.root_module);
|
||||
|
||||
// Freetype
|
||||
// Freetype. We always include this even if our font backend doesn't
|
||||
// use it because Dear Imgui uses Freetype.
|
||||
_ = b.systemIntegrationOption("freetype", .{}); // Shows it in help
|
||||
if (self.config.font_backend.hasFreetype()) {
|
||||
if (b.lazyDependency("freetype", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.@"enable-libpng" = true,
|
||||
})) |freetype_dep| {
|
||||
step.root_module.addImport(
|
||||
"freetype",
|
||||
freetype_dep.module("freetype"),
|
||||
);
|
||||
if (b.lazyDependency("freetype", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.@"enable-libpng" = true,
|
||||
})) |freetype_dep| {
|
||||
step.root_module.addImport(
|
||||
"freetype",
|
||||
freetype_dep.module("freetype"),
|
||||
);
|
||||
|
||||
if (b.systemIntegrationOption("freetype", .{})) {
|
||||
step.linkSystemLibrary2("bzip2", dynamic_link_opts);
|
||||
step.linkSystemLibrary2("freetype2", dynamic_link_opts);
|
||||
} else {
|
||||
step.linkLibrary(freetype_dep.artifact("freetype"));
|
||||
try static_libs.append(
|
||||
b.allocator,
|
||||
freetype_dep.artifact("freetype").getEmittedBin(),
|
||||
);
|
||||
}
|
||||
if (b.systemIntegrationOption("freetype", .{})) {
|
||||
step.linkSystemLibrary2("bzip2", dynamic_link_opts);
|
||||
step.linkSystemLibrary2("freetype2", dynamic_link_opts);
|
||||
} else {
|
||||
step.linkLibrary(freetype_dep.artifact("freetype"));
|
||||
try static_libs.append(
|
||||
b.allocator,
|
||||
freetype_dep.artifact("freetype").getEmittedBin(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,15 +478,19 @@ pub fn add(
|
||||
}
|
||||
|
||||
// cimgui
|
||||
if (b.lazyDependency("cimgui", .{
|
||||
if (b.lazyDependency("dcimgui", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
})) |cimgui_dep| {
|
||||
step.root_module.addImport("cimgui", cimgui_dep.module("cimgui"));
|
||||
step.linkLibrary(cimgui_dep.artifact("cimgui"));
|
||||
.freetype = true,
|
||||
.@"backend-metal" = target.result.os.tag.isDarwin(),
|
||||
.@"backend-osx" = target.result.os.tag == .macos,
|
||||
.@"backend-opengl3" = target.result.os.tag != .macos,
|
||||
})) |dep| {
|
||||
step.root_module.addImport("dcimgui", dep.module("dcimgui"));
|
||||
step.linkLibrary(dep.artifact("dcimgui"));
|
||||
try static_libs.append(
|
||||
b.allocator,
|
||||
cimgui_dep.artifact("cimgui").getEmittedBin(),
|
||||
dep.artifact("dcimgui").getEmittedBin(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2783,6 +2783,22 @@ keybind: Keybinds = .{},
|
||||
/// the same time as the `iTime` uniform, allowing you to compute the
|
||||
/// time since the change by subtracting this from `iTime`.
|
||||
///
|
||||
/// * `float iTimeFocus` - Timestamp when the surface last gained iFocus.
|
||||
///
|
||||
/// When the surface gains focus, this is set to the current value of
|
||||
/// `iTime`, similar to how `iTimeCursorChange` works. This allows you
|
||||
/// to compute the time since focus was gained or lost by calculating
|
||||
/// `iTime - iTimeFocus`. Use this to create animations that restart
|
||||
/// when the terminal regains focus.
|
||||
///
|
||||
/// * `int iFocus` - Current focus state of the surface.
|
||||
///
|
||||
/// Set to 1.0 when the surface is focused, 0.0 when unfocused. This
|
||||
/// allows shaders to detect unfocused state and avoid animation artifacts
|
||||
/// from large time deltas caused by infrequent "deceptive frames"
|
||||
/// (e.g., modifier key presses, link hover events in unfocused split panes).
|
||||
/// Check `iFocus > 0` to determine if the surface is currently focused.
|
||||
///
|
||||
/// If the shader fails to compile, the shader will be ignored. Any errors
|
||||
/// related to shader compilation will not show up as configuration errors
|
||||
/// and only show up in the log, since shader compilation happens after
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const cimgui = @import("cimgui");
|
||||
const cimgui = @import("dcimgui");
|
||||
const OptionAsAlt = @import("config.zig").OptionAsAlt;
|
||||
|
||||
/// A generic key input event. This is the information that is necessary
|
||||
@@ -696,7 +696,7 @@ pub const Key = enum(c_int) {
|
||||
}
|
||||
|
||||
/// Returns the cimgui key constant for this key.
|
||||
pub fn imguiKey(self: Key) ?c_uint {
|
||||
pub fn imguiKey(self: Key) ?c_int {
|
||||
return switch (self) {
|
||||
.key_a => cimgui.c.ImGuiKey_A,
|
||||
.key_b => cimgui.c.ImGuiKey_B,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const assert = @import("../quirks.zig").inlineAssert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const cimgui = @import("cimgui");
|
||||
const cimgui = @import("dcimgui");
|
||||
const terminal = @import("../terminal/main.zig");
|
||||
|
||||
/// A cell being inspected. This duplicates much of the data in
|
||||
@@ -55,24 +55,22 @@ pub const Cell = struct {
|
||||
y: usize,
|
||||
) void {
|
||||
// We have a selected cell, show information about it.
|
||||
_ = cimgui.c.igBeginTable(
|
||||
_ = cimgui.c.ImGui_BeginTable(
|
||||
"table_cursor",
|
||||
2,
|
||||
cimgui.c.ImGuiTableFlags_None,
|
||||
.{ .x = 0, .y = 0 },
|
||||
0,
|
||||
);
|
||||
defer cimgui.c.igEndTable();
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Grid Position");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Grid Position");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("row=%d col=%d", y, x);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("row=%d col=%d", y, x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,18 +80,18 @@ pub const Cell = struct {
|
||||
// the single glyph in an image view so it looks _identical_ to the
|
||||
// terminal.
|
||||
codepoint: {
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Codepoints");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Codepoints");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
if (cimgui.c.igBeginListBox("##codepoints", .{ .x = 0, .y = 0 })) {
|
||||
defer cimgui.c.igEndListBox();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
if (cimgui.c.ImGui_BeginListBox("##codepoints", .{ .x = 0, .y = 0 })) {
|
||||
defer cimgui.c.ImGui_EndListBox();
|
||||
|
||||
if (self.codepoint == 0) {
|
||||
_ = cimgui.c.igSelectable_Bool("(empty)", false, 0, .{});
|
||||
_ = cimgui.c.ImGui_SelectableEx("(empty)", false, 0, .{});
|
||||
break :codepoint;
|
||||
}
|
||||
|
||||
@@ -102,42 +100,42 @@ pub const Cell = struct {
|
||||
{
|
||||
const key = std.fmt.bufPrintZ(&buf, "U+{X}", .{self.codepoint}) catch
|
||||
"<internal error>";
|
||||
_ = cimgui.c.igSelectable_Bool(key.ptr, false, 0, .{});
|
||||
_ = cimgui.c.ImGui_SelectableEx(key.ptr, false, 0, .{});
|
||||
}
|
||||
|
||||
// All extras
|
||||
for (self.cps) |cp| {
|
||||
const key = std.fmt.bufPrintZ(&buf, "U+{X}", .{cp}) catch
|
||||
"<internal error>";
|
||||
_ = cimgui.c.igSelectable_Bool(key.ptr, false, 0, .{});
|
||||
_ = cimgui.c.ImGui_SelectableEx(key.ptr, false, 0, .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Character width property
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Width Property");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText(@tagName(self.wide));
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Width Property");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text(@tagName(self.wide));
|
||||
|
||||
// If we have a color then we show the color
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Foreground Color");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Foreground Color");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
switch (self.style.fg_color) {
|
||||
.none => cimgui.c.igText("default"),
|
||||
.none => cimgui.c.ImGui_Text("default"),
|
||||
.palette => |idx| {
|
||||
const rgb = t.colors.palette.current[idx];
|
||||
cimgui.c.igValue_Int("Palette", idx);
|
||||
cimgui.c.ImGui_Text("Palette %d", idx);
|
||||
var color: [3]f32 = .{
|
||||
@as(f32, @floatFromInt(rgb.r)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.g)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.b)) / 255,
|
||||
};
|
||||
_ = cimgui.c.igColorEdit3(
|
||||
_ = cimgui.c.ImGui_ColorEdit3(
|
||||
"color_fg",
|
||||
&color,
|
||||
cimgui.c.ImGuiColorEditFlags_DisplayHex |
|
||||
@@ -152,7 +150,7 @@ pub const Cell = struct {
|
||||
@as(f32, @floatFromInt(rgb.g)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.b)) / 255,
|
||||
};
|
||||
_ = cimgui.c.igColorEdit3(
|
||||
_ = cimgui.c.ImGui_ColorEdit3(
|
||||
"color_fg",
|
||||
&color,
|
||||
cimgui.c.ImGuiColorEditFlags_DisplayHex |
|
||||
@@ -162,21 +160,21 @@ pub const Cell = struct {
|
||||
},
|
||||
}
|
||||
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Background Color");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Background Color");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
switch (self.style.bg_color) {
|
||||
.none => cimgui.c.igText("default"),
|
||||
.none => cimgui.c.ImGui_Text("default"),
|
||||
.palette => |idx| {
|
||||
const rgb = t.colors.palette.current[idx];
|
||||
cimgui.c.igValue_Int("Palette", idx);
|
||||
cimgui.c.ImGui_Text("Palette %d", idx);
|
||||
var color: [3]f32 = .{
|
||||
@as(f32, @floatFromInt(rgb.r)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.g)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.b)) / 255,
|
||||
};
|
||||
_ = cimgui.c.igColorEdit3(
|
||||
_ = cimgui.c.ImGui_ColorEdit3(
|
||||
"color_bg",
|
||||
&color,
|
||||
cimgui.c.ImGuiColorEditFlags_DisplayHex |
|
||||
@@ -191,7 +189,7 @@ pub const Cell = struct {
|
||||
@as(f32, @floatFromInt(rgb.g)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.b)) / 255,
|
||||
};
|
||||
_ = cimgui.c.igColorEdit3(
|
||||
_ = cimgui.c.ImGui_ColorEdit3(
|
||||
"color_bg",
|
||||
&color,
|
||||
cimgui.c.ImGuiColorEditFlags_DisplayHex |
|
||||
@@ -209,17 +207,17 @@ pub const Cell = struct {
|
||||
inline for (styles) |style| style: {
|
||||
if (!@field(self.style.flags, style)) break :style;
|
||||
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText(style.ptr);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text(style.ptr);
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("true");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("true");
|
||||
}
|
||||
}
|
||||
|
||||
cimgui.c.igTextDisabled("(Any styles not shown are not currently set)");
|
||||
cimgui.c.ImGui_TextDisabled("(Any styles not shown are not currently set)");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const cimgui = @import("cimgui");
|
||||
const cimgui = @import("dcimgui");
|
||||
const terminal = @import("../terminal/main.zig");
|
||||
|
||||
/// Render cursor information with a table already open.
|
||||
@@ -7,57 +7,57 @@ pub fn renderInTable(
|
||||
cursor: *const terminal.Screen.Cursor,
|
||||
) void {
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Position (x, y)");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Position (x, y)");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("(%d, %d)", cursor.x, cursor.y);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("(%d, %d)", cursor.x, cursor.y);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Style");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Style");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%s", @tagName(cursor.cursor_style).ptr);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%s", @tagName(cursor.cursor_style).ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor.pending_wrap) {
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Pending Wrap");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Pending Wrap");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%s", if (cursor.pending_wrap) "true".ptr else "false".ptr);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%s", if (cursor.pending_wrap) "true".ptr else "false".ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a color then we show the color
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Foreground Color");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Foreground Color");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
switch (cursor.style.fg_color) {
|
||||
.none => cimgui.c.igText("default"),
|
||||
.none => cimgui.c.ImGui_Text("default"),
|
||||
.palette => |idx| {
|
||||
const rgb = t.colors.palette.current[idx];
|
||||
cimgui.c.igValue_Int("Palette", idx);
|
||||
cimgui.c.ImGui_Text("Palette %d", idx);
|
||||
var color: [3]f32 = .{
|
||||
@as(f32, @floatFromInt(rgb.r)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.g)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.b)) / 255,
|
||||
};
|
||||
_ = cimgui.c.igColorEdit3(
|
||||
_ = cimgui.c.ImGui_ColorEdit3(
|
||||
"color_fg",
|
||||
&color,
|
||||
cimgui.c.ImGuiColorEditFlags_DisplayHex |
|
||||
@@ -72,7 +72,7 @@ pub fn renderInTable(
|
||||
@as(f32, @floatFromInt(rgb.g)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.b)) / 255,
|
||||
};
|
||||
_ = cimgui.c.igColorEdit3(
|
||||
_ = cimgui.c.ImGui_ColorEdit3(
|
||||
"color_fg",
|
||||
&color,
|
||||
cimgui.c.ImGuiColorEditFlags_DisplayHex |
|
||||
@@ -82,21 +82,21 @@ pub fn renderInTable(
|
||||
},
|
||||
}
|
||||
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Background Color");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Background Color");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
switch (cursor.style.bg_color) {
|
||||
.none => cimgui.c.igText("default"),
|
||||
.none => cimgui.c.ImGui_Text("default"),
|
||||
.palette => |idx| {
|
||||
const rgb = t.colors.palette.current[idx];
|
||||
cimgui.c.igValue_Int("Palette", idx);
|
||||
cimgui.c.ImGui_Text("Palette %d", idx);
|
||||
var color: [3]f32 = .{
|
||||
@as(f32, @floatFromInt(rgb.r)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.g)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.b)) / 255,
|
||||
};
|
||||
_ = cimgui.c.igColorEdit3(
|
||||
_ = cimgui.c.ImGui_ColorEdit3(
|
||||
"color_bg",
|
||||
&color,
|
||||
cimgui.c.ImGuiColorEditFlags_DisplayHex |
|
||||
@@ -111,7 +111,7 @@ pub fn renderInTable(
|
||||
@as(f32, @floatFromInt(rgb.g)) / 255,
|
||||
@as(f32, @floatFromInt(rgb.b)) / 255,
|
||||
};
|
||||
_ = cimgui.c.igColorEdit3(
|
||||
_ = cimgui.c.ImGui_ColorEdit3(
|
||||
"color_bg",
|
||||
&color,
|
||||
cimgui.c.ImGuiColorEditFlags_DisplayHex |
|
||||
@@ -129,14 +129,14 @@ pub fn renderInTable(
|
||||
inline for (styles) |style| style: {
|
||||
if (!@field(cursor.style.flags, style)) break :style;
|
||||
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText(style.ptr);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text(style.ptr);
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("true");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const input = @import("../input.zig");
|
||||
const CircBuf = @import("../datastruct/main.zig").CircBuf;
|
||||
const cimgui = @import("cimgui");
|
||||
const cimgui = @import("dcimgui");
|
||||
|
||||
/// Circular buffer of key events.
|
||||
pub const EventRing = CircBuf(Event, undefined);
|
||||
@@ -72,30 +72,28 @@ pub const Event = struct {
|
||||
|
||||
/// Render this event in the inspector GUI.
|
||||
pub fn render(self: *const Event) void {
|
||||
_ = cimgui.c.igBeginTable(
|
||||
_ = cimgui.c.ImGui_BeginTable(
|
||||
"##event",
|
||||
2,
|
||||
cimgui.c.ImGuiTableFlags_None,
|
||||
.{ .x = 0, .y = 0 },
|
||||
0,
|
||||
);
|
||||
defer cimgui.c.igEndTable();
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
if (self.binding.len > 0) {
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Triggered Binding");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Triggered Binding");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
|
||||
const height: f32 = height: {
|
||||
const item_count: f32 = @floatFromInt(@min(self.binding.len, 5));
|
||||
const padding = cimgui.c.igGetStyle().*.FramePadding.y * 2;
|
||||
break :height cimgui.c.igGetTextLineHeightWithSpacing() * item_count + padding;
|
||||
const padding = cimgui.c.ImGui_GetStyle().*.FramePadding.y * 2;
|
||||
break :height cimgui.c.ImGui_GetTextLineHeightWithSpacing() * item_count + padding;
|
||||
};
|
||||
if (cimgui.c.igBeginListBox("##bindings", .{ .x = 0, .y = height })) {
|
||||
defer cimgui.c.igEndListBox();
|
||||
if (cimgui.c.ImGui_BeginListBox("##bindings", .{ .x = 0, .y = height })) {
|
||||
defer cimgui.c.ImGui_EndListBox();
|
||||
for (self.binding) |action| {
|
||||
_ = cimgui.c.igSelectable_Bool(
|
||||
_ = cimgui.c.ImGui_SelectableEx(
|
||||
@tagName(action).ptr,
|
||||
false,
|
||||
cimgui.c.ImGuiSelectableFlags_None,
|
||||
@@ -106,64 +104,64 @@ pub const Event = struct {
|
||||
}
|
||||
|
||||
pty: {
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Encoding to Pty");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Encoding to Pty");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
if (self.pty.len == 0) {
|
||||
cimgui.c.igTextDisabled("(no data)");
|
||||
cimgui.c.ImGui_TextDisabled("(no data)");
|
||||
break :pty;
|
||||
}
|
||||
|
||||
self.renderPty() catch {
|
||||
cimgui.c.igTextDisabled("(error rendering pty data)");
|
||||
cimgui.c.ImGui_TextDisabled("(error rendering pty data)");
|
||||
break :pty;
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Action");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%s", @tagName(self.event.action).ptr);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Action");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%s", @tagName(self.event.action).ptr);
|
||||
}
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Key");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%s", @tagName(self.event.key).ptr);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Key");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%s", @tagName(self.event.key).ptr);
|
||||
}
|
||||
if (!self.event.mods.empty()) {
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Mods");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
if (self.event.mods.shift) cimgui.c.igText("shift ");
|
||||
if (self.event.mods.ctrl) cimgui.c.igText("ctrl ");
|
||||
if (self.event.mods.alt) cimgui.c.igText("alt ");
|
||||
if (self.event.mods.super) cimgui.c.igText("super ");
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Mods");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
if (self.event.mods.shift) cimgui.c.ImGui_Text("shift ");
|
||||
if (self.event.mods.ctrl) cimgui.c.ImGui_Text("ctrl ");
|
||||
if (self.event.mods.alt) cimgui.c.ImGui_Text("alt ");
|
||||
if (self.event.mods.super) cimgui.c.ImGui_Text("super ");
|
||||
}
|
||||
if (self.event.composing) {
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Composing");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("true");
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Composing");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("true");
|
||||
}
|
||||
utf8: {
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("UTF-8");
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("UTF-8");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
if (self.event.utf8.len == 0) {
|
||||
cimgui.c.igTextDisabled("(empty)");
|
||||
cimgui.c.ImGui_TextDisabled("(empty)");
|
||||
break :utf8;
|
||||
}
|
||||
|
||||
self.renderUtf8(self.event.utf8) catch {
|
||||
cimgui.c.igTextDisabled("(error rendering utf-8)");
|
||||
cimgui.c.ImGui_TextDisabled("(error rendering utf-8)");
|
||||
break :utf8;
|
||||
};
|
||||
}
|
||||
@@ -187,13 +185,11 @@ pub const Event = struct {
|
||||
try writer.writeByte(0);
|
||||
|
||||
// Render as a textbox
|
||||
_ = cimgui.c.igInputText(
|
||||
_ = cimgui.c.ImGui_InputText(
|
||||
"##utf8",
|
||||
&buf,
|
||||
buf_stream.getWritten().len - 1,
|
||||
cimgui.c.ImGuiInputTextFlags_ReadOnly,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -223,13 +219,11 @@ pub const Event = struct {
|
||||
try writer.writeByte(0);
|
||||
|
||||
// Render as a textbox
|
||||
_ = cimgui.c.igInputText(
|
||||
_ = cimgui.c.ImGui_InputText(
|
||||
"##pty",
|
||||
&buf,
|
||||
buf_stream.getWritten().len - 1,
|
||||
cimgui.c.ImGuiInputTextFlags_ReadOnly,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,167 +1,161 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const cimgui = @import("cimgui");
|
||||
const cimgui = @import("dcimgui");
|
||||
const terminal = @import("../terminal/main.zig");
|
||||
const units = @import("units.zig");
|
||||
|
||||
pub fn render(page: *const terminal.Page) void {
|
||||
cimgui.c.igPushID_Ptr(page);
|
||||
defer cimgui.c.igPopID();
|
||||
cimgui.c.ImGui_PushIDPtr(page);
|
||||
defer cimgui.c.ImGui_PopID();
|
||||
|
||||
_ = cimgui.c.igBeginTable(
|
||||
_ = cimgui.c.ImGui_BeginTable(
|
||||
"##page_state",
|
||||
2,
|
||||
cimgui.c.ImGuiTableFlags_None,
|
||||
.{ .x = 0, .y = 0 },
|
||||
0,
|
||||
);
|
||||
defer cimgui.c.igEndTable();
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Memory Size");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Memory Size");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d bytes (%d KiB)", page.memory.len, units.toKibiBytes(page.memory.len));
|
||||
cimgui.c.igText("%d VM pages", page.memory.len / std.heap.page_size_min);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d bytes (%d KiB)", page.memory.len, units.toKibiBytes(page.memory.len));
|
||||
cimgui.c.ImGui_Text("%d VM pages", page.memory.len / std.heap.page_size_min);
|
||||
}
|
||||
}
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Unique Styles");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Unique Styles");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d", page.styles.count());
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d", page.styles.count());
|
||||
}
|
||||
}
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Grapheme Entries");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Grapheme Entries");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d", page.graphemeCount());
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d", page.graphemeCount());
|
||||
}
|
||||
}
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Capacity");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Capacity");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
_ = cimgui.c.igBeginTable(
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
_ = cimgui.c.ImGui_BeginTable(
|
||||
"##capacity",
|
||||
2,
|
||||
cimgui.c.ImGuiTableFlags_None,
|
||||
.{ .x = 0, .y = 0 },
|
||||
0,
|
||||
);
|
||||
defer cimgui.c.igEndTable();
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
const cap = page.capacity;
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Columns");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Columns");
|
||||
}
|
||||
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d", @as(u32, @intCast(cap.cols)));
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d", @as(u32, @intCast(cap.cols)));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Rows");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Rows");
|
||||
}
|
||||
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d", @as(u32, @intCast(cap.rows)));
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d", @as(u32, @intCast(cap.rows)));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Unique Styles");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Unique Styles");
|
||||
}
|
||||
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d", @as(u32, @intCast(cap.styles)));
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d", @as(u32, @intCast(cap.styles)));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Grapheme Bytes");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Grapheme Bytes");
|
||||
}
|
||||
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d", cap.grapheme_bytes);
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d", cap.grapheme_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Size");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Size");
|
||||
}
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
_ = cimgui.c.igBeginTable(
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
_ = cimgui.c.ImGui_BeginTable(
|
||||
"##size",
|
||||
2,
|
||||
cimgui.c.ImGuiTableFlags_None,
|
||||
.{ .x = 0, .y = 0 },
|
||||
0,
|
||||
);
|
||||
defer cimgui.c.igEndTable();
|
||||
defer cimgui.c.ImGui_EndTable();
|
||||
|
||||
const size = page.size;
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Columns");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Columns");
|
||||
}
|
||||
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d", @as(u32, @intCast(size.cols)));
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d", @as(u32, @intCast(size.cols)));
|
||||
}
|
||||
}
|
||||
{
|
||||
cimgui.c.igTableNextRow(cimgui.c.ImGuiTableRowFlags_None, 0);
|
||||
cimgui.c.ImGui_TableNextRow();
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(0);
|
||||
cimgui.c.igText("Rows");
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(0);
|
||||
cimgui.c.ImGui_Text("Rows");
|
||||
}
|
||||
|
||||
{
|
||||
_ = cimgui.c.igTableSetColumnIndex(1);
|
||||
cimgui.c.igText("%d", @as(u32, @intCast(size.rows)));
|
||||
_ = cimgui.c.ImGui_TableSetColumnIndex(1);
|
||||
cimgui.c.ImGui_Text("%d", @as(u32, @intCast(size.rows)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const cimgui = @import("cimgui");
|
||||
const cimgui = @import("dcimgui");
|
||||
const terminal = @import("../terminal/main.zig");
|
||||
const CircBuf = @import("../datastruct/main.zig").CircBuf;
|
||||
const Surface = @import("../Surface.zig");
|
||||
@@ -83,7 +83,7 @@ pub const VTEvent = struct {
|
||||
/// Returns true if the event passes the given filter.
|
||||
pub fn passFilter(
|
||||
self: *const VTEvent,
|
||||
filter: *cimgui.c.ImGuiTextFilter,
|
||||
filter: *const cimgui.c.ImGuiTextFilter,
|
||||
) bool {
|
||||
// Check our main string
|
||||
if (cimgui.c.ImGuiTextFilter_PassFilter(
|
||||
@@ -318,19 +318,18 @@ pub const VTHandler = struct {
|
||||
|
||||
/// Exclude certain actions by tag.
|
||||
filter_exclude: ActionTagSet = .initMany(&.{.print}),
|
||||
filter_text: *cimgui.c.ImGuiTextFilter,
|
||||
filter_text: cimgui.c.ImGuiTextFilter = .{},
|
||||
|
||||
const ActionTagSet = std.EnumSet(terminal.Parser.Action.Tag);
|
||||
|
||||
pub fn init(surface: *Surface) VTHandler {
|
||||
return .{
|
||||
.surface = surface,
|
||||
.filter_text = cimgui.c.ImGuiTextFilter_ImGuiTextFilter(""),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *VTHandler) void {
|
||||
cimgui.c.ImGuiTextFilter_destroy(self.filter_text);
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub fn vt(
|
||||
@@ -371,7 +370,7 @@ pub const VTHandler = struct {
|
||||
errdefer ev.deinit(alloc);
|
||||
|
||||
// Check if the event passes the filter
|
||||
if (!ev.passFilter(self.filter_text)) {
|
||||
if (!ev.passFilter(&self.filter_text)) {
|
||||
ev.deinit(alloc);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -116,6 +116,10 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
/// True if the window is focused
|
||||
focused: bool,
|
||||
|
||||
/// Flag to indicate that our focus state changed for custom
|
||||
/// shaders to update their state.
|
||||
custom_shader_focused_changed: bool = false,
|
||||
|
||||
/// The most recent scrollbar state. We use this as a cache to
|
||||
/// determine if we need to notify the apprt that there was a
|
||||
/// scrollbar change.
|
||||
@@ -746,6 +750,8 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
.current_cursor_color = @splat(0),
|
||||
.previous_cursor_color = @splat(0),
|
||||
.cursor_change_time = 0,
|
||||
.time_focus = 0,
|
||||
.focus = 1, // assume focused initially
|
||||
},
|
||||
.bg_image_buffer = undefined,
|
||||
|
||||
@@ -1008,8 +1014,13 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
///
|
||||
/// Must be called on the render thread.
|
||||
pub fn setFocus(self: *Self, focus: bool) !void {
|
||||
assert(self.focused != focus);
|
||||
|
||||
self.focused = focus;
|
||||
|
||||
// Flag that we need to update our custom shaders
|
||||
self.custom_shader_focused_changed = true;
|
||||
|
||||
// If we're not focused, then we want to stop the display link
|
||||
// because it is a waste of resources and we can move to pure
|
||||
// change-driven updates.
|
||||
@@ -2255,6 +2266,8 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
// We only need to do this if we have custom shaders.
|
||||
if (!self.has_custom_shaders) return;
|
||||
|
||||
const uniforms = &self.custom_shader_uniforms;
|
||||
|
||||
const now = try std.time.Instant.now();
|
||||
defer self.last_frame_time = now;
|
||||
const first_frame_time = self.first_frame_time orelse t: {
|
||||
@@ -2264,23 +2277,23 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
const last_frame_time = self.last_frame_time orelse now;
|
||||
|
||||
const since_ns: f32 = @floatFromInt(now.since(first_frame_time));
|
||||
self.custom_shader_uniforms.time = since_ns / std.time.ns_per_s;
|
||||
uniforms.time = since_ns / std.time.ns_per_s;
|
||||
|
||||
const delta_ns: f32 = @floatFromInt(now.since(last_frame_time));
|
||||
self.custom_shader_uniforms.time_delta = delta_ns / std.time.ns_per_s;
|
||||
uniforms.time_delta = delta_ns / std.time.ns_per_s;
|
||||
|
||||
self.custom_shader_uniforms.frame += 1;
|
||||
uniforms.frame += 1;
|
||||
|
||||
const screen = self.size.screen;
|
||||
const padding = self.size.padding;
|
||||
const cell = self.size.cell;
|
||||
|
||||
self.custom_shader_uniforms.resolution = .{
|
||||
uniforms.resolution = .{
|
||||
@floatFromInt(screen.width),
|
||||
@floatFromInt(screen.height),
|
||||
1,
|
||||
};
|
||||
self.custom_shader_uniforms.channel_resolution[0] = .{
|
||||
uniforms.channel_resolution[0] = .{
|
||||
@floatFromInt(screen.width),
|
||||
@floatFromInt(screen.height),
|
||||
1,
|
||||
@@ -2345,8 +2358,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
@as(f32, @floatFromInt(cursor.color[3])) / 255.0,
|
||||
};
|
||||
|
||||
const uniforms = &self.custom_shader_uniforms;
|
||||
|
||||
const cursor_changed: bool =
|
||||
!std.meta.eql(new_cursor, uniforms.current_cursor) or
|
||||
!std.meta.eql(cursor_color, uniforms.current_cursor_color);
|
||||
@@ -2359,6 +2370,19 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
uniforms.cursor_change_time = uniforms.time;
|
||||
}
|
||||
}
|
||||
|
||||
// Update focus uniforms
|
||||
uniforms.focus = @intFromBool(self.focused);
|
||||
|
||||
// If we need to update the time our focus state changed
|
||||
// then update it to our current frame time. This may not be
|
||||
// exactly correct since it is frame time, not exact focus
|
||||
// time, but focus time on its own isn't exactly correct anyways
|
||||
// since it comes async from a message.
|
||||
if (self.custom_shader_focused_changed and self.focused) {
|
||||
uniforms.time_focus = uniforms.time;
|
||||
self.custom_shader_focused_changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the terminal state to GPU cells stored in CPU memory. These
|
||||
|
||||
@@ -16,6 +16,8 @@ layout(binding = 1, std140) uniform Globals {
|
||||
uniform vec4 iCurrentCursorColor;
|
||||
uniform vec4 iPreviousCursorColor;
|
||||
uniform float iTimeCursorChange;
|
||||
uniform float iTimeFocus;
|
||||
uniform int iFocus;
|
||||
};
|
||||
|
||||
layout(binding = 0) uniform sampler2D iChannel0;
|
||||
|
||||
41
src/renderer/shaders/test_shadertoy_focus.glsl
Normal file
41
src/renderer/shaders/test_shadertoy_focus.glsl
Normal file
@@ -0,0 +1,41 @@
|
||||
// Test shader for iTimeFocus and iFocus
|
||||
// Shows border when focused, green fade that restarts on each focus gain
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
|
||||
// Sample the terminal content
|
||||
vec4 terminal = texture2D(iChannel0, uv);
|
||||
vec3 color = terminal.rgb;
|
||||
|
||||
if (iFocus > 0) {
|
||||
// FOCUSED: Add border and fading green overlay
|
||||
|
||||
// Calculate time since focus was gained
|
||||
float timeSinceFocus = iTime - iTimeFocus;
|
||||
|
||||
// Green fade: starts at 1.0 (full green), fades to 0.0 over 3 seconds
|
||||
float fadeOut = max(0.0, 1.0 - (timeSinceFocus / 3.0));
|
||||
|
||||
// Add green overlay that fades out
|
||||
color = mix(color, vec3(0.0, 1.0, 0.0), fadeOut * 0.4);
|
||||
|
||||
// Add border (5 pixels)
|
||||
float borderSize = 5.0;
|
||||
vec2 pixelCoord = fragCoord;
|
||||
bool isBorder = pixelCoord.x < borderSize ||
|
||||
pixelCoord.x > iResolution.x - borderSize ||
|
||||
pixelCoord.y < borderSize ||
|
||||
pixelCoord.y > iResolution.y - borderSize;
|
||||
|
||||
if (isBorder) {
|
||||
// Bright cyan border that pulses subtly
|
||||
float pulse = sin(timeSinceFocus * 2.0) * 0.1 + 0.9;
|
||||
color = vec3(0.0, 1.0, 1.0) * pulse;
|
||||
}
|
||||
} else {
|
||||
// UNFOCUSED: Solid red overlay (no border)
|
||||
color = mix(color, vec3(1.0, 0.0, 0.0), 0.3);
|
||||
}
|
||||
|
||||
fragColor = vec4(color, 1.0);
|
||||
}
|
||||
@@ -25,6 +25,8 @@ pub const Uniforms = extern struct {
|
||||
current_cursor_color: [4]f32 align(16),
|
||||
previous_cursor_color: [4]f32 align(16),
|
||||
cursor_change_time: f32 align(4),
|
||||
time_focus: f32 align(4),
|
||||
focus: i32 align(4),
|
||||
};
|
||||
|
||||
/// The target to load shaders for.
|
||||
@@ -412,3 +414,4 @@ test "shadertoy to glsl" {
|
||||
|
||||
const test_crt = @embedFile("shaders/test_shadertoy_crt.glsl");
|
||||
const test_invalid = @embedFile("shaders/test_shadertoy_invalid.glsl");
|
||||
const test_focus = @embedFile("shaders/test_shadertoy_focus.glsl");
|
||||
|
||||
Reference in New Issue
Block a user