Pārlūkot izejas kodu

display(macOS): add console text and background color config

Add consoleTextColor and consoleBackgroundColor properties which are
converted to NSData when saved into the configuration dictionary.
Add hexString extension to NSColor.
Add changeColor Javascript function that sets the hterm colors.
Call the changeColor Javascript function in the terminal view
controller.
kt programs 3 gadi atpakaļ
vecāks
revīzija
788f372f33

+ 4 - 0
Configuration/UTMAppleConfiguration.swift

@@ -45,6 +45,10 @@ final class UTMAppleConfiguration: UTMConfigurable, Codable, ObservableObject {
     
     @Published var consoleTheme: String?
     
+    @Published var consoleTextColor: NSColor?
+    
+    @Published var consoleBackgroundColor: NSColor?
+    
     @Published var consoleFont: String?
     
     @Published var consoleFontSize: NSNumber?

+ 4 - 0
Configuration/UTMConfigurable.h

@@ -15,6 +15,7 @@
 //
 
 #import <Foundation/Foundation.h>
+#import <AppKit/AppKit.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -29,6 +30,9 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, nullable, copy) NSString *notes;
 
 @property (nonatomic, nullable, copy) NSString *consoleTheme;
+// TODO: Maybe use CGColor (But hard to handle)
+@property (nonatomic, nullable, copy) NSColor *consoleTextColor;
+@property (nonatomic, nullable, copy) NSColor *consoleBackgroundColor;
 @property (nonatomic, nullable, copy) NSString *consoleFont;
 @property (nonatomic, nullable, copy) NSNumber *consoleFontSize;
 @property (nonatomic, assign) BOOL consoleCursorBlink;

+ 30 - 0
Configuration/UTMQemuConfiguration+Display.m

@@ -25,6 +25,8 @@ const NSString *const kUTMConfigDisplayRetinaKey = @"DisplayRetina";
 const NSString *const kUTMConfigDisplayUpscalerKey = @"DisplayUpscaler";
 const NSString *const kUTMConfigDisplayDownscalerKey = @"DisplayDownscaler";
 const NSString *const kUTMConfigConsoleThemeKey = @"ConsoleTheme";
+const NSString *const kUTMConfigConsoleTextColorKey = @"ConsoleTextColor";
+const NSString *const kUTMConfigConsoleBackgroundColorKey = @"ConsoleBackgroundColor";
 const NSString *const kUTMConfigConsoleFontKey = @"ConsoleFont";
 const NSString *const kUTMConfigConsoleFontSizeKey = @"ConsoleFontSize";
 const NSString *const kUTMConfigConsoleBlinkKey = @"ConsoleBlink";
@@ -54,6 +56,12 @@ const NSString *const kUTMConfigDisplayCardKey = @"DisplayCard";
     if (self.consoleTheme.length == 0) {
         self.consoleTheme = @"Default";
     }
+    if (self.consoleTextColor == nil) {
+        self.consoleTextColor = [NSColor whiteColor];
+    }
+    if (self.consoleBackgroundColor == nil) {
+        self.consoleBackgroundColor = [NSColor blackColor];
+    }
     if (self.consoleFontSize.integerValue == 0) {
         self.consoleFontSize = @12;
     }
@@ -140,6 +148,28 @@ const NSString *const kUTMConfigDisplayCardKey = @"DisplayCard";
     return self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleThemeKey];
 }
 
+- (void)setConsoleTextColor:(NSColor *)consoleTextColor {
+    [self propertyWillChange];
+    NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:consoleTextColor requiringSecureCoding:YES error:nil];
+    self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleTextColorKey] = colorData;
+}
+
+- (NSColor *)consoleTextColor {
+    NSData *colorData = self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleTextColorKey];
+    return [NSKeyedUnarchiver unarchivedObjectOfClass:[NSColor class] fromData:colorData error:nil];
+}
+
+- (void)setConsoleBackgroundColor:(NSColor *)consoleBackgroundColor {
+    [self propertyWillChange];
+    NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:consoleBackgroundColor requiringSecureCoding:YES error:nil];
+    self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleBackgroundColorKey] = colorData;
+}
+
+- (NSColor *)consoleBackgroundColor {
+    NSData *colorData = self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleBackgroundColorKey];
+    return [NSKeyedUnarchiver unarchivedObjectOfClass:[NSColor class] fromData:colorData error:nil];
+}
+
 - (void)setConsoleFont:(NSString *)consoleFont {
     [self propertyWillChange];
     self.rootDict[kUTMConfigDisplayKey][kUTMConfigConsoleFontKey] = consoleFont;

+ 6 - 0
Platform/Shared/HTerm/terminal.js

@@ -210,6 +210,12 @@ function setupHterm() {
     window.term = term;
 };
 
+function changeColor(foregroundColor, backgroundColor) {
+    const term = new hterm.Terminal();
+    term.getPrefs().set('foreground-color', foregroundColor)
+    term.getPrefs().set('background-color', backgroundColor)
+}
+
 function changeFont(fontFamily, fontSize) {
     const term = new hterm.Terminal();
     term.getPrefs().set('font-family', fontFamily);

+ 17 - 0
Platform/Shared/VMConfigDisplayConsoleView.swift

@@ -20,6 +20,21 @@ import SwiftUI
 struct VMConfigDisplayConsoleView<Config: ObservableObject & UTMConfigurable>: View {
     @ObservedObject var config: Config
     
+    private var textColor: Binding<Color> {
+        Binding<Color> {
+            Color(config.consoleTextColor ?? .white)
+        } set: { newValue in
+            config.consoleTextColor = NSColor(newValue)
+        }
+    }
+    private var backgroundColor: Binding<Color> {
+        Binding<Color> {
+            Color(config.consoleBackgroundColor ?? .black)
+        } set: { newValue in
+            config.consoleBackgroundColor = NSColor(newValue)
+        }
+    }
+        
     var body: some View {
         let fontSizeObserver = Binding<Int> {
             Int(truncating: config.consoleFontSize ?? 1)
@@ -28,6 +43,8 @@ struct VMConfigDisplayConsoleView<Config: ObservableObject & UTMConfigurable>: V
         }
         Section(header: Text("Style"), footer: EmptyView().padding(.bottom)) {
             VMConfigStringPicker(selection: $config.consoleTheme, label: Text("Theme"), rawValues: UTMQemuConfiguration.supportedConsoleThemes(), displayValues: UTMQemuConfiguration.supportedConsoleThemes())
+            ColorPicker("Text Color", selection: textColor)
+            ColorPicker("Background Color", selection: backgroundColor)
             VMConfigStringPicker(selection: $config.consoleFont, label: Text("Font"), rawValues: UTMQemuConfiguration.supportedConsoleFonts(), displayValues: UTMQemuConfiguration.supportedConsoleFonts())
             HStack {
                 Stepper(value: fontSizeObserver, in: 1...72) {

+ 12 - 0
Platform/UTMExtensions.swift

@@ -169,6 +169,18 @@ extension NSImage {
     }
 }
 
+extension NSColor {
+    var hexString: String? {
+        guard let rgbColor = self.usingColorSpace(.sRGB) else {
+            return nil
+        }
+        let red = Int(round(rgbColor.redComponent * 0xFF))
+        let green = Int(round(rgbColor.greenComponent * 0xFF))
+        let blue = Int(round(rgbColor.blueComponent * 0xFF))
+        return String(format: "#%02X%02X%02X", red, green, blue)
+    }
+}
+
 @propertyWrapper
 struct Setting<T> {
     private(set) var keyName: String

+ 11 - 0
Platform/macOS/Display/VMDisplayTerminalWindowController.swift

@@ -84,6 +84,17 @@ extension VMDisplayTerminalWindowController: WKNavigationDelegate {
     }
     
     func updateSettings() {
+        if let consoleTextColor = vmQemuConfig?.consoleTextColor,
+           let consoleBackgroundColor = vmQemuConfig?.consoleBackgroundColor,
+           // TODO: Should use default colors, or keep it as if let?
+           let consoleTextColorString = consoleTextColor.hexString,
+           let consoleBackgroundColorString = consoleBackgroundColor.hexString {
+            webView.evaluateJavaScript("changeColor('\(consoleTextColorString)', '\(consoleBackgroundColorString)');") { (_, err) in
+                if let error = err {
+                    logger.error("changeColor error: \(error)")
+                }
+            }
+        }
         if let consoleFont = vmQemuConfig?.consoleFont {
             let consoleFontSize = vmQemuConfig?.consoleFontSize?.intValue ?? 12
             webView.evaluateJavaScript("changeFont('\(consoleFont)', \(consoleFontSize));") { (_, err) in