Skip to content

Commit

Permalink
Add legacy mode option to fix tooltip positioning issue
Browse files Browse the repository at this point in the history
  • Loading branch information
liuyd-dev committed Sep 13, 2023
1 parent 1ec7e4f commit 3d7804d
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/SyncTrayzor/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
</PathConfiguration>
<DefaultUserConfiguration Version="10">
<ShowTrayIconOnlyOnClose>false</ShowTrayIconOnlyOnClose>
<ShowTrayToolTipInLegacyMode>false</ShowTrayToolTipInLegacyMode>
<MinimizeToTray>false</MinimizeToTray>
<CloseToTray>true</CloseToTray>
<ShowDeviceConnectivityBalloons>false</ShowDeviceConnectivityBalloons>
Expand Down
12 changes: 12 additions & 0 deletions src/SyncTrayzor/NotifyIcon/NotifyIconManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace SyncTrayzor.NotifyIcon
public interface INotifyIconManager : IDisposable
{
bool ShowOnlyOnClose { get; set; }
bool ShowInLegacyMode { get; set; }
bool MinimizeToTray { get; set; }
bool CloseToTray { get; set; }
Dictionary<string, bool> FolderNotificationsEnabled { get; set; }
Expand Down Expand Up @@ -59,6 +60,17 @@ public bool ShowOnlyOnClose
}
}

private bool _showInLegacyMode;
public bool ShowInLegacyMode
{
get => this._showInLegacyMode;
set
{
this._showInLegacyMode = value;
Utils.TrayToolTipWorkaround.SetLegacyMode(value, this.taskbarIcon);
}
}

public bool MinimizeToTray { get; set; }

private bool _closeToTray;
Expand Down
1 change: 1 addition & 0 deletions src/SyncTrayzor/Pages/Settings/SettingsView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
<CheckBox DockPanel.Dock="Top" IsChecked="{Binding ShowDeviceConnectivityBalloons.Value}" Content="{l:Loc SettingsView_ShowDeviceConnectivityBalloons}"/>
<CheckBox DockPanel.Dock="Top" IsChecked="{Binding ShowDeviceOrFolderRejectedBalloons.Value}" Content="{l:Loc SettingsView_ShowDeviceOrFolderRejectedBalloons}"/>
<CheckBox DockPanel.Dock="Top" IsChecked="{Binding ShowTrayIconOnlyOnClose.Value}" Content="{l:Loc SettingsView_OnlyShowTrayIconOnClose}"/>
<CheckBox DockPanel.Dock="Top" IsChecked="{Binding ShowTrayToolTipInLegacyMode.Value}" Content="{l:Loc SettingsView_ShowTrayToolTipInLegacyMode}"/>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,5,0,0">
<Label Padding="0,0,5,0" Target="{Binding ElementName=IconAnimationModeSelect}" VerticalAlignment="Center" Content="{l:Loc SettingsView_AnimateTrayIcon}"/>
<ComboBox x:Name="IconAnimationModeSelect" ItemsSource="{Binding IconAnimationModes}" SelectedValuePath="Value" SelectedValue="{Binding IconAnimationMode.Value}"/>
Expand Down
3 changes: 3 additions & 0 deletions src/SyncTrayzor/Pages/Settings/SettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public class SettingsViewModel : Screen
public SettingItem<bool> PauseDevicesOnMeteredNetworks { get; }

public SettingItem<bool> ShowTrayIconOnlyOnClose { get; }

public SettingItem<bool> ShowTrayToolTipInLegacyMode { get; }
public SettingItem<bool> ShowSynchronizedBalloonEvenIfNothingDownloaded { get; }
public SettingItem<bool> ShowDeviceConnectivityBalloons { get; }
public SettingItem<bool> ShowDeviceOrFolderRejectedBalloons { get; }
Expand Down Expand Up @@ -138,6 +140,7 @@ public class SettingsViewModel : Screen
this.PauseDevicesOnMeteredNetworksSupported = meteredNetworkManager.IsSupportedByWindows;

this.ShowTrayIconOnlyOnClose = this.CreateBasicSettingItem(x => x.ShowTrayIconOnlyOnClose);
this.ShowTrayToolTipInLegacyMode = this.CreateBasicSettingItem(x => x.ShowTrayToolTipInLegacyMode);
this.ShowSynchronizedBalloonEvenIfNothingDownloaded = this.CreateBasicSettingItem(x => x.ShowSynchronizedBalloonEvenIfNothingDownloaded);
this.ShowDeviceConnectivityBalloons = this.CreateBasicSettingItem(x => x.ShowDeviceConnectivityBalloons);
this.ShowDeviceOrFolderRejectedBalloons = this.CreateBasicSettingItem(x => x.ShowDeviceOrFolderRejectedBalloons);
Expand Down
13 changes: 11 additions & 2 deletions src/SyncTrayzor/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/SyncTrayzor/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1002,4 +1002,7 @@ Please donate to my charity fundraising campaign.</value>
<data name="BarAlertsView_IntelXeGraphics_DismissLink" xml:space="preserve">
<value>Dismiss</value>
</data>
<data name="SettingsView_ShowTrayToolTipInLegacyMode" xml:space="preserve">
<value>Show TrayToolTip in legacy mode (Experimental): Check this option if the TrayToolTip is displaying in the wrong location to attempt to fix it.</value>
</data>
</root>
5 changes: 4 additions & 1 deletion src/SyncTrayzor/Services/Config/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public int Version
}

public bool ShowTrayIconOnlyOnClose { get; set; }
public bool ShowTrayToolTipInLegacyMode { get; set; }
public bool MinimizeToTray { get; set; }
public bool CloseToTray { get; set; }
public bool ShowDeviceConnectivityBalloons { get; set; }
Expand Down Expand Up @@ -78,6 +79,7 @@ public Configuration()
// Default configuration is for a portable setup.

this.ShowTrayIconOnlyOnClose = false;
this.ShowTrayToolTipInLegacyMode = false;
this.MinimizeToTray = false;
this.CloseToTray = true;
this.ShowSynchronizedBalloonEvenIfNothingDownloaded = false;
Expand Down Expand Up @@ -116,6 +118,7 @@ public Configuration()
public Configuration(Configuration other)
{
this.ShowTrayIconOnlyOnClose = other.ShowTrayIconOnlyOnClose;
this.ShowTrayToolTipInLegacyMode = other.ShowTrayToolTipInLegacyMode;
this.MinimizeToTray = other.MinimizeToTray;
this.CloseToTray = other.CloseToTray;
this.ShowSynchronizedBalloonEvenIfNothingDownloaded = other.ShowSynchronizedBalloonEvenIfNothingDownloaded;
Expand Down Expand Up @@ -153,7 +156,7 @@ public Configuration(Configuration other)

public override string ToString()
{
return $"<Configuration ShowTrayIconOnlyOnClose={this.ShowTrayIconOnlyOnClose} MinimizeToTray={this.MinimizeToTray} CloseToTray={this.CloseToTray} " +
return $"<Configuration ShowTrayIconOnlyOnClose={this.ShowTrayIconOnlyOnClose} ShowTrayToolTipInLegacyMode={this.ShowTrayToolTipInLegacyMode} MinimizeToTray={this.MinimizeToTray} CloseToTray={this.CloseToTray} " +
$"ShowDeviceConnectivityBalloons={this.ShowDeviceConnectivityBalloons} ShowDeviceOrFolderRejectedBalloons={this.ShowDeviceOrFolderRejectedBalloons} " +
$"SyncthingAddress={this.SyncthingAddress} StartSyncthingAutomatically={this.StartSyncthingAutomatically} " +
$"SyncthingCommandLineFlags=[{String.Join(",", this.SyncthingCommandLineFlags)}] " +
Expand Down
1 change: 1 addition & 0 deletions src/SyncTrayzor/Services/ConfigurationApplicator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ private void ApplyNewConfiguration(Configuration configuration)
this.notifyIconManager.MinimizeToTray = configuration.MinimizeToTray;
this.notifyIconManager.CloseToTray = configuration.CloseToTray;
this.notifyIconManager.ShowOnlyOnClose = configuration.ShowTrayIconOnlyOnClose;
this.notifyIconManager.ShowInLegacyMode = configuration.ShowTrayToolTipInLegacyMode;
this.notifyIconManager.FolderNotificationsEnabled = configuration.Folders.ToDictionary(x => x.ID, x => x.NotificationsEnabled);
this.notifyIconManager.ShowSynchronizedBalloonEvenIfNothingDownloaded = configuration.ShowSynchronizedBalloonEvenIfNothingDownloaded;
this.notifyIconManager.ShowDeviceConnectivityBalloons = configuration.ShowDeviceConnectivityBalloons;
Expand Down
7 changes: 4 additions & 3 deletions src/SyncTrayzor/SyncTrayzor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
<WarningLevel>4</WarningLevel>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<IsWebBootstrapper>false</IsWebBootstrapper>
<TargetFrameworkProfile />
<GenerateResourceMSBuildArchitecture>CurrentArchitecture</GenerateResourceMSBuildArchitecture>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
Expand All @@ -27,11 +30,8 @@
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
<GenerateResourceMSBuildArchitecture>CurrentArchitecture</GenerateResourceMSBuildArchitecture>
</PropertyGroup>
<PropertyGroup>
</PropertyGroup>
Expand Down Expand Up @@ -339,6 +339,7 @@
<Compile Include="Utils\StringExtensions.cs" />
<Compile Include="Utils\SynchronizedEventDispatcher.cs" />
<Compile Include="Design\ViewModelLocator.cs" />
<Compile Include="Utils\TrayToolTipWorkaround.cs" />
<Compile Include="Xaml\ActivateBehaviour.cs" />
<Compile Include="Xaml\CultureAwareBinding.cs" />
<Compile Include="Xaml\GridLengthToAbsoluteConverter.cs" />
Expand Down
92 changes: 92 additions & 0 deletions src/SyncTrayzor/Utils/TrayToolTipWorkaround.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using System.Windows;
using System.Reflection;
using Hardcodet.Wpf.TaskbarNotification;
using Hardcodet.Wpf.TaskbarNotification.Interop;

namespace SyncTrayzor.Utils
{
public static class TrayToolTipWorkaround {
private static bool hasFixed = false;
private static bool legacyMode = false;

private static void setTipTextMode(TaskbarIcon taskbarIcon) {
if (!hasFixed || taskbarIcon == null) {
return;
}

if (taskbarIcon.TrayToolTip == null && taskbarIcon.TrayToolTipResolved != null) {
// icon data
FieldInfo iconDataField = typeof(TaskbarIcon).GetField("iconData", BindingFlags.NonPublic | BindingFlags.Instance);
if (iconDataField == null) {
return;
}

NotifyIconData iconData = (NotifyIconData) iconDataField.GetValue(taskbarIcon);
IconDataMembers flags = IconDataMembers.Tip;
if (legacyMode) {
flags |= IconDataMembers.UseLegacyToolTips;
}
if (iconData.ValidMembers != flags) {
iconData.ValidMembers = flags;

// get util type
Type utilType = typeof(TaskbarIcon).GetTypeInfo().Assembly.GetType("Hardcodet.Wpf.TaskbarNotification.Util");
if (utilType == null)
{
return;
}

// get write method
MethodInfo writeIconDataMethod = utilType.GetMethod("WriteIconData", new Type[] { typeof(NotifyIconData).MakeByRefType(), typeof(NotifyCommand) });
if (writeIconDataMethod == null)
{
return;
}

writeIconDataMethod.Invoke(null, new object[] { iconData, NotifyCommand.Modify });
}
}
}

private static void doFix(TaskbarIcon taskbarIcon) {
// register new DependencyProperty
DependencyProperty newProperty = DependencyProperty.Register("NewToolTipText", typeof(string), typeof(TaskbarIcon),
new FrameworkPropertyMetadata(string.Empty, (d, e) => {
// call the origin callback func
MethodInfo originCbMethod = typeof(TaskbarIcon).GetMethod("ToolTipTextPropertyChanged", BindingFlags.Static | BindingFlags.NonPublic);
originCbMethod?.Invoke(null, new object[] { d, e });
// try to refresh legacy mode
TaskbarIcon t = d as TaskbarIcon;
setTipTextMode(t);
})
);

// back up tip text
string tipTextBackup = string.Empty;
if (taskbarIcon != null && !string.IsNullOrEmpty(taskbarIcon.ToolTipText)) {
tipTextBackup = taskbarIcon.ToolTipText;
}

// set new ToolTipTextProperty, every time update ToolTipText, will run own func
var propertyFieldInfo = typeof(TaskbarIcon).GetField("ToolTipTextProperty", BindingFlags.Static | BindingFlags.Public);
propertyFieldInfo.SetValue(null, newProperty);

// set tip text
if (taskbarIcon != null) {
taskbarIcon.ToolTipText = tipTextBackup;
}
}

public static void SetLegacyMode(bool _legacyMode, TaskbarIcon taskbarIcon)
{
if(_legacyMode && !hasFixed) {
doFix(taskbarIcon);
hasFixed = true;
}
legacyMode = _legacyMode;
setTipTextMode(taskbarIcon);
}
}
}

0 comments on commit 3d7804d

Please sign in to comment.