Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions WineFix/Patches/SubToolColumnsPatch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using System.Windows;
using HarmonyLib;
using AffinityPluginLoader.Core;

namespace WineFix.Patches
{
/// <summary>
/// Keeps the sub-tool panel's column count across a studio switch.
///
/// The sub-tool panel is a ToolTray like the main tool pane. SubToolPanel.ToggleVisibility
/// gives it two columns when the current tool has more than ten sub-tools (the shape tools)
/// and one otherwise, and runs whenever the tool changes. A studio switch also raises
/// CurrentWorkspaceChanged, and every ToolTray handles that by setting Columns to
/// ToolSettings.ToolPaneColumns -- the main tool pane's setting. With a one-column tool pane
/// the shape tools came back as a single column running the height of the window, until
/// the next tool change put two columns back.
///
/// After that handler, the sub-tool panel's tray gets its own rule back. The main tool pane
/// is left alone.
/// </summary>
public static class SubToolColumnsPatch
{
private static PropertyInfo _toolhostProperty;
private static PropertyInfo _subToolRootProperty;
private static PropertyInfo _columnsProperty;
private static PropertyInfo _currentToolProperty;

public static void ApplyPatches(Harmony harmony)
{
Logger.Info("Applying SubToolColumns patch...");

var serifAssembly = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.GetName().Name == "Serif.Affinity");
if (serifAssembly == null)
{
Logger.Error("Serif.Affinity assembly not found");
return;
}

var trayType = serifAssembly.GetType("Serif.Affinity.UI.Controls.Tools.ToolTray");
var hostType = serifAssembly.GetType("Serif.Affinity.UI.Controls.Tools.ToolHost");
var windowType = serifAssembly.GetType("Serif.Affinity.UI.AffinityWindow");
var handler = trayType == null ? null
: AccessTools.Method(trayType, "WorkspaceService_CurrentWorkspaceChanged");

_toolhostProperty = windowType == null ? null : AccessTools.Property(windowType, "Toolhost");
_subToolRootProperty = hostType == null ? null : AccessTools.Property(hostType, "SubToolRoot");
_columnsProperty = trayType == null ? null : AccessTools.Property(trayType, "Columns");
_currentToolProperty = trayType == null ? null : AccessTools.Property(trayType, "CurrentTool");

if (handler == null || _toolhostProperty == null || _subToolRootProperty == null
|| _columnsProperty == null || _currentToolProperty == null)
{
Logger.Error("ToolTray/ToolHost members not found; sub-tool columns left as they are");
return;
}

harmony.Patch(handler, postfix: new HarmonyMethod(typeof(SubToolColumnsPatch), nameof(CurrentWorkspaceChanged_Postfix)));
Logger.Info("Patched ToolTray.WorkspaceService_CurrentWorkspaceChanged");
}

public static void CurrentWorkspaceChanged_Postfix(object __instance)
{
try
{
var window = Application.Current?.MainWindow;
if (window == null || !_toolhostProperty.DeclaringType.IsInstanceOfType(window))
return;
var toolhost = _toolhostProperty.GetValue(window);
if (toolhost == null || !ReferenceEquals(_subToolRootProperty.GetValue(toolhost), __instance))
return;

// SubToolPanel.ToggleVisibility's rule.
var tool = _currentToolProperty.GetValue(__instance);
if (tool == null)
return;
var children = AccessTools.Property(tool.GetType(), "Children")?.GetValue(tool) as ICollection;
if (children == null)
return;
object columns = children.Count > 10 ? 2 : 1;
if (_columnsProperty.PropertyType == typeof(int?))
columns = (int?)(int)columns;
_columnsProperty.SetValue(__instance, columns);
}
catch (Exception ex)
{
Logger.Error("SubToolColumns: " + ex.Message);
}
}
}
}
15 changes: 15 additions & 0 deletions WineFix/WineFixPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class WineFixPlugin : AffinityPlugin
public const string SettingWidenStubFix = "widen_stub_fix";
public const string SettingBezierSplitGuard = "bezier_split_guard";
public const string SettingCommandLineFileOpen = "command_line_file_open";
public const string SettingSubToolColumns = "sub_tool_columns_fix";

public override PluginSettingsDefinition DefineSettings()
{
Expand Down Expand Up @@ -69,6 +70,10 @@ public override PluginSettingsDefinition DefineSettings()
defaultValue: true,
restartRequired: true,
description: "Fix opening files from the command line or desktop file manager.")
.AddBool(SettingSubToolColumns, "Sub-tool panel: Keep its columns across studio switches",
defaultValue: true,
restartRequired: true,
description: "A studio switch gives the sub-tool panel the main tool pane's column count, so with a one-column tool pane the shape tools come back as one column running the height of the window until the next tool change. Put back the sub-tool panel's own rule (two columns for more than ten sub-tools) after a studio switch.")
.AddSection("Crash Fixes")
.AddBool(SettingForceSyncFontEnum, "Force synchronous font enumeration",
defaultValue: true,
Expand Down Expand Up @@ -111,6 +116,16 @@ public override void OnPatch(Harmony harmony, IPluginContext context)
context.Patch("MainWindowLoaded fix",
h => Patches.MainWindowLoadedPatch.ApplyPatches(h));

if (context.Settings.GetEffectiveValue<bool>(SettingSubToolColumns))
{
context.Patch("SubToolColumns fix",
h => Patches.SubToolColumnsPatch.ApplyPatches(h));
}
else
{
Logger.Info("Skipping SubToolColumns fix (setting: disabled)");
}

if (context.Settings.GetEffectiveValue<bool>(SettingForceSyncFontEnum))
{
context.Patch("FontEnumeration fix",
Expand Down
1 change: 1 addition & 0 deletions docs/winefix/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ WineFix uses plugin ID `winefix`. Settings are stored in `apl/config/winefix.tom
| `color_picker_sampling_mode` | enum | `native` | No | Controls how the color picker samples color values. See [Sampling Modes](index.md#color-picker-sampling-modes). |
| `canva_sign_in_helper` | bool | `true` | Yes | Patch the Canva sign-in dialog to include a helper textbox and instructions to complete sign-in without a protocol URL handler. |
| `command_line_file_open` | bool | `true` | Yes | Fix opening files from the command line or desktop file manager. Bypasses Affinity's broken `ProcessCommandLineArguments` which references a WinRT type missing in Wine. |
| `sub_tool_columns_fix` | bool | `true` | Yes | Keep the sub-tool panel's own column count (two for more than ten sub-tools) after a studio switch, which otherwise gives it the main tool pane's. |

#### `color_picker_magnifier_fix`

Expand Down