Skip to content

Commit 0431d0b

Browse files
committed
Replace gtk with zenity and kdialog
1 parent 801b203 commit 0431d0b

File tree

10 files changed

+200
-293
lines changed

10 files changed

+200
-293
lines changed

AssetRipper.NativeDialogs/AssetRipper.NativeDialogs.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
</PropertyGroup>
1414

1515
<ItemGroup>
16-
<PackageReference Include="GtkSharp" Version="3.24.24.117-develop" />
1716
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.26100.2" />
1817
</ItemGroup>
1918

AssetRipper.NativeDialogs/ConfirmationDialog.cs

Lines changed: 72 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.ComponentModel;
2+
using System.Diagnostics;
23
using System.Diagnostics.CodeAnalysis;
34
using System.Runtime.Versioning;
45
using TerraFX.Interop.Windows;
@@ -111,51 +112,88 @@ public Options(string message, Type type = Type.OkCancel)
111112
}
112113

113114
[SupportedOSPlatform("linux")]
114-
private static Task<bool?> ConfirmLinux(Options options)
115+
private static async Task<bool?> ConfirmLinux(Options options)
115116
{
116-
if (Gtk.Global.IsSupported)
117+
string escapedMessage = ProcessExecutor.EscapeString(options.Message);
118+
if (await LinuxHelper.HasZenity())
117119
{
118-
return ConfirmLinuxGtk(options);
120+
Process process = new()
121+
{
122+
StartInfo = new()
123+
{
124+
FileName = "zenity",
125+
RedirectStandardOutput = true,
126+
RedirectStandardError = true,
127+
},
128+
};
129+
130+
process.StartInfo.ArgumentList.Add("--question");
131+
process.StartInfo.ArgumentList.Add("--text");
132+
process.StartInfo.ArgumentList.Add(escapedMessage);
133+
if (options.Type != Type.YesNo)
134+
{
135+
string escapedTrueLabel = ProcessExecutor.EscapeString(options.TrueLabel);
136+
string escapedFalseLabel = ProcessExecutor.EscapeString(options.FalseLabel);
137+
138+
process.StartInfo.ArgumentList.Add("--ok-label");
139+
process.StartInfo.ArgumentList.Add(escapedTrueLabel);
140+
process.StartInfo.ArgumentList.Add("--cancel-label");
141+
process.StartInfo.ArgumentList.Add(escapedFalseLabel);
142+
}
143+
144+
process.BeginOutputReadLine();
145+
process.BeginErrorReadLine();
146+
147+
if (!process.Start())
148+
{
149+
return null; // Failed to start the process
150+
}
151+
152+
await process.WaitForExitAsync();
153+
154+
return process.ExitCode switch
155+
{
156+
0 => true, // User clicked OK or Yes
157+
1 => false, // User clicked Cancel or No
158+
_ => null, // An error occurred
159+
};
119160
}
120-
else
161+
else if (await LinuxHelper.HasKDialog())
121162
{
122-
// Fallback
123-
return Task.FromResult<bool?>(null);
124-
}
125-
}
163+
Process process = new()
164+
{
165+
StartInfo = new()
166+
{
167+
FileName = "kdialog",
168+
RedirectStandardOutput = true,
169+
RedirectStandardError = true,
170+
},
171+
};
126172

127-
[SupportedOSPlatform("linux")]
128-
private static async Task<bool?> ConfirmLinuxGtk(Options options)
129-
{
130-
bool? result;
131-
while (!GtkHelper.TryInitialize())
132-
{
133-
await GtkHelper.Delay(); // Wait for the GTK initialization to complete
134-
}
173+
process.StartInfo.ArgumentList.Add(options.Type is Type.YesNo ? "--yesno" : "--okcancel");
174+
process.StartInfo.ArgumentList.Add(escapedMessage);
135175

136-
try
137-
{
138-
using Gtk.MessageDialog md = new(
139-
null,
140-
Gtk.DialogFlags.Modal,
141-
Gtk.MessageType.Info,
142-
options.Type == Type.OkCancel ? Gtk.ButtonsType.OkCancel : Gtk.ButtonsType.YesNo,
143-
options.Message
144-
);
176+
process.BeginOutputReadLine();
177+
process.BeginErrorReadLine();
178+
179+
if (!process.Start())
180+
{
181+
return null; // Failed to start the process
182+
}
183+
184+
await process.WaitForExitAsync();
145185

146-
int response = md.Run();
147-
result = response switch
186+
return process.ExitCode switch
148187
{
149-
(int)Gtk.ResponseType.Ok or (int)Gtk.ResponseType.Yes => true,
150-
(int)Gtk.ResponseType.Cancel or (int)Gtk.ResponseType.No => false,
151-
_ => throw new($"Unexpected response type: {response}"),
188+
0 => true, // User clicked OK or Yes
189+
1 => false, // User clicked Cancel or No
190+
_ => null, // An error occurred
152191
};
153192
}
154-
finally
193+
else
155194
{
156-
GtkHelper.Shutdown(); // Ensure GTK is properly shut down after use
195+
// Fallback
196+
return null;
157197
}
158-
159-
return result;
160198
}
161199
}

AssetRipper.NativeDialogs/GtkHelper.cs

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Runtime.Versioning;
2+
3+
namespace AssetRipper.NativeDialogs;
4+
5+
[SupportedOSPlatform("linux")]
6+
internal static class LinuxHelper
7+
{
8+
private static bool? hasZenity;
9+
private static bool? hasKDialog;
10+
11+
public static async Task<bool> HasSupportedBackend()
12+
{
13+
if (hasZenity is null)
14+
{
15+
await HasZenity();
16+
}
17+
if (hasKDialog is null)
18+
{
19+
await HasKDialog();
20+
}
21+
return hasZenity == true || hasKDialog == true;
22+
}
23+
24+
public static async Task<bool> HasZenity()
25+
{
26+
return hasZenity ??= await ProcessExecutor.HasCommand("zenity");
27+
}
28+
29+
public static async Task<bool> HasKDialog()
30+
{
31+
return hasKDialog ??= await ProcessExecutor.HasCommand("kdialog");
32+
}
33+
}

AssetRipper.NativeDialogs/MessageDialog.cs

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -79,41 +79,20 @@ private static Task MessageMacOS(Options options)
7979
}
8080

8181
[SupportedOSPlatform("linux")]
82-
private static Task MessageLinux(Options options)
82+
private static async Task MessageLinux(Options options)
8383
{
84-
if (Gtk.Global.IsSupported)
85-
{
86-
return MessageLinuxGtk(options);
87-
}
88-
else
89-
{
90-
// Fallback
91-
return Task.CompletedTask;
92-
}
93-
}
94-
95-
[SupportedOSPlatform("linux")]
96-
private static async Task MessageLinuxGtk(Options options)
97-
{
98-
while (!GtkHelper.TryInitialize())
84+
string escapedMessage = ProcessExecutor.EscapeString(options.Message);
85+
if (await LinuxHelper.HasZenity())
9986
{
100-
await GtkHelper.Delay(); // Wait for the GTK initialization to complete
87+
await ProcessExecutor.TryRun("zenity", "--info", "--text", escapedMessage);
10188
}
102-
103-
try
89+
else if (await LinuxHelper.HasKDialog())
10490
{
105-
using Gtk.MessageDialog md = new(
106-
null,
107-
Gtk.DialogFlags.Modal,
108-
Gtk.MessageType.Info,
109-
Gtk.ButtonsType.Ok,
110-
options.Message
111-
);
112-
md.Run();
91+
await ProcessExecutor.TryRun("kdialog", "--msgbox", escapedMessage);
11392
}
114-
finally
93+
else
11594
{
116-
GtkHelper.Shutdown(); // Ensure GTK is properly shut down after use
95+
// Fallback: do nothing
11796
}
11897
}
11998
}

AssetRipper.NativeDialogs/NativeDialog.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
public static class NativeDialog
44
{
5-
public static bool Supported =>
6-
OperatingSystem.IsWindows() ||
7-
OperatingSystem.IsMacOS() ||
8-
(OperatingSystem.IsLinux() && Gtk.Global.IsSupported);
5+
private static bool SupportedLinux { get; } = OperatingSystem.IsLinux() && LinuxHelper.HasSupportedBackend().WaitForResult();
6+
public static bool Supported => OperatingSystem.IsWindows() || OperatingSystem.IsMacOS() || (OperatingSystem.IsLinux() && SupportedLinux);
7+
8+
private static T WaitForResult<T>(this Task<T> task)
9+
{
10+
task.Wait();
11+
return task.Result;
12+
}
913
}

AssetRipper.NativeDialogs/OpenFileDialog.cs

Lines changed: 24 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -70,51 +70,21 @@ public static class OpenFileDialog
7070
}
7171

7272
[SupportedOSPlatform("linux")]
73-
private static Task<string?> OpenFileLinux()
73+
private static async Task<string?> OpenFileLinux()
7474
{
75-
if (Gtk.Global.IsSupported)
75+
if (await LinuxHelper.HasZenity())
7676
{
77-
return OpenFileLinuxGtk();
77+
return await ProcessExecutor.TryRun("zenity", "--file-selection");
7878
}
79-
else
80-
{
81-
// Fallback
82-
return Task.FromResult<string?>(null);
83-
}
84-
}
85-
86-
[SupportedOSPlatform("linux")]
87-
private static async Task<string?> OpenFileLinuxGtk()
88-
{
89-
Debug.Assert(Gtk.Global.IsSupported);
90-
91-
string? result;
92-
while (!GtkHelper.TryInitialize())
93-
{
94-
await GtkHelper.Delay(); // Wait for the GTK initialization to complete
95-
}
96-
97-
try
79+
else if (await LinuxHelper.HasKDialog())
9880
{
99-
using Gtk.FileChooserNative dlg = new(
100-
"Open a file", null,
101-
Gtk.FileChooserAction.Open, "Open", "Cancel");
102-
103-
if (dlg.Run() == (int)Gtk.ResponseType.Accept)
104-
{
105-
result = dlg.Filename;
106-
}
107-
else
108-
{
109-
result = null; // User canceled the dialog
110-
}
81+
return await ProcessExecutor.TryRun("kdialog", "--getopenfilename");
11182
}
112-
finally
83+
else
11384
{
114-
GtkHelper.Shutdown(); // Ensure GTK is properly shut down after use
85+
// Fallback
86+
return null;
11587
}
116-
117-
return result;
11888
}
11989

12090
public static Task<string[]?> OpenFiles()
@@ -211,52 +181,30 @@ public static class OpenFileDialog
211181
}
212182

213183
[SupportedOSPlatform("linux")]
214-
private static Task<string[]?> OpenFilesLinux()
184+
private static async Task<string[]?> OpenFilesLinux()
215185
{
216-
if (Gtk.Global.IsSupported)
186+
if (await LinuxHelper.HasZenity())
217187
{
218-
return OpenFilesLinuxGtk();
219-
}
220-
else
221-
{
222-
// Fallback
223-
return Task.FromResult<string[]?>(null);
224-
}
225-
}
226-
227-
[SupportedOSPlatform("linux")]
228-
private static async Task<string[]?> OpenFilesLinuxGtk()
229-
{
230-
Debug.Assert(Gtk.Global.IsSupported);
231-
232-
string[]? result;
233-
while (!GtkHelper.TryInitialize())
234-
{
235-
await GtkHelper.Delay(); // Wait for the GTK initialization to complete
236-
}
237-
238-
try
239-
{
240-
using Gtk.FileChooserNative dlg = new(
241-
"Open files", null,
242-
Gtk.FileChooserAction.Open, "Open", "Cancel");
243-
244-
dlg.SelectMultiple = true; // Allow multiple folder selection
245-
246-
if (dlg.Run() == (int)Gtk.ResponseType.Accept)
188+
string? output = await ProcessExecutor.TryRun("zenity", "--file-selection", "--multiple");
189+
if (string.IsNullOrEmpty(output))
247190
{
248-
result = dlg.Filenames;
191+
return null; // User canceled the dialog
249192
}
250-
else
193+
return output.Split('|');
194+
}
195+
else if (await LinuxHelper.HasKDialog())
196+
{
197+
string? output = await ProcessExecutor.TryRun("kdialog", "--getopenfilenames");
198+
if (string.IsNullOrEmpty(output))
251199
{
252-
result = null; // User canceled the dialog
200+
return null; // User canceled the dialog
253201
}
202+
return output.Split('\n');
254203
}
255-
finally
204+
else
256205
{
257-
GtkHelper.Shutdown(); // Ensure GTK is properly shut down after use
206+
// Fallback
207+
return null;
258208
}
259-
260-
return result;
261209
}
262210
}

0 commit comments

Comments
 (0)