diff --git a/TheXamlGuy.TaskbarGroup.Flyout.Foundation/Drag.cs b/TheXamlGuy.TaskbarGroup.Flyout.Foundation/Drag.cs new file mode 100644 index 0000000..071ece5 --- /dev/null +++ b/TheXamlGuy.TaskbarGroup.Flyout.Foundation/Drag.cs @@ -0,0 +1,9 @@ +using Windows.UI.Xaml; + +namespace TheXamlGuy.TaskbarGroup.Flyout.Foundation +{ + public record class Drag(DragEventArgs DragEventArgs) where TTarget : UIElement + { + public TTarget Target { get; } + } +} diff --git a/TheXamlGuy.TaskbarGroup.Flyout.Foundation/DropTarget.cs b/TheXamlGuy.TaskbarGroup.Flyout.Foundation/DropTarget.cs index 8d40a37..583a7de 100644 --- a/TheXamlGuy.TaskbarGroup.Flyout.Foundation/DropTarget.cs +++ b/TheXamlGuy.TaskbarGroup.Flyout.Foundation/DropTarget.cs @@ -30,20 +30,34 @@ namespace TheXamlGuy.TaskbarGroup.Flyout.Foundation base.OnAttached(); } - private void OnDrop(object sender, DragEventArgs args) + private object CreateDragMessage(object sender, DragEventArgs args) { - if (Mediator is not null) - { - var dropMessageType = typeof(Drop<>).MakeGenericType(sender.GetType()); - var dropMessage = Activator.CreateInstance(dropMessageType, args); + var dropMessageType = typeof(Drag<>).MakeGenericType(sender.GetType()); + return Activator.CreateInstance(dropMessageType, args); + } - Mediator.HandleAsync(dropMessage); - } + private object CreateDropMessage(object sender, DragEventArgs args) + { + var dropMessageType = typeof(Drop<>).MakeGenericType(sender.GetType()); + return Activator.CreateInstance(dropMessageType, args); } private void OnDragOver(object sender, DragEventArgs args) { - args.AcceptedOperation = DataPackageOperation.Link; + if (Mediator is not null) + { + var message = CreateDragMessage(sender, args); + Mediator.HandleAsync(message); + } + } + + private void OnDrop(object sender, DragEventArgs args) + { + if (Mediator is not null) + { + var message = CreateDropMessage(sender, args); + Mediator.HandleAsync(message); + } } } } diff --git a/TheXamlGuy.TaskbarGroup.Flyout.Foundation/IDragHandler.cs b/TheXamlGuy.TaskbarGroup.Flyout.Foundation/IDragHandler.cs new file mode 100644 index 0000000..19dab35 --- /dev/null +++ b/TheXamlGuy.TaskbarGroup.Flyout.Foundation/IDragHandler.cs @@ -0,0 +1,10 @@ +using TheXamlGuy.TaskbarGroup.Core; +using Windows.UI.Xaml; + +namespace TheXamlGuy.TaskbarGroup.Flyout.Foundation +{ + public interface IDragHandler : IAsyncMessageHandler> where TTarget : UIElement + { + + } +} diff --git a/TheXamlGuy.TaskbarGroup.Flyout.Foundation/TheXamlGuy.TaskbarGroup.Flyout.Foundation.csproj b/TheXamlGuy.TaskbarGroup.Flyout.Foundation/TheXamlGuy.TaskbarGroup.Flyout.Foundation.csproj index b7da097..194ae72 100644 --- a/TheXamlGuy.TaskbarGroup.Flyout.Foundation/TheXamlGuy.TaskbarGroup.Flyout.Foundation.csproj +++ b/TheXamlGuy.TaskbarGroup.Flyout.Foundation/TheXamlGuy.TaskbarGroup.Flyout.Foundation.csproj @@ -122,10 +122,12 @@ PackageReference + + diff --git a/TheXamlGuy.TaskbarGroup.Flyout/TheXamlGuy.TaskbarGroup.Flyout.csproj b/TheXamlGuy.TaskbarGroup.Flyout/TheXamlGuy.TaskbarGroup.Flyout.csproj index 7e8d2b5..f6a1961 100644 --- a/TheXamlGuy.TaskbarGroup.Flyout/TheXamlGuy.TaskbarGroup.Flyout.csproj +++ b/TheXamlGuy.TaskbarGroup.Flyout/TheXamlGuy.TaskbarGroup.Flyout.csproj @@ -78,6 +78,7 @@ + diff --git a/TheXamlGuy.TaskbarGroup.Flyout/Views/TaskbarButtonGroupDragHandler.cs b/TheXamlGuy.TaskbarGroup.Flyout/Views/TaskbarButtonGroupDragHandler.cs new file mode 100644 index 0000000..ff1b887 --- /dev/null +++ b/TheXamlGuy.TaskbarGroup.Flyout/Views/TaskbarButtonGroupDragHandler.cs @@ -0,0 +1,24 @@ +using System.Threading; +using System.Threading.Tasks; +using TheXamlGuy.TaskbarGroup.Flyout.Foundation; +using Windows.ApplicationModel.DataTransfer; + +namespace TheXamlGuy.TaskbarGroup.Flyout +{ + public class TaskbarButtonGroupDragHandler : IDragHandler + { + public Task Handle(Drag message, CancellationToken canellationToken = default) + { + message.DragEventArgs.AcceptedOperation = DataPackageOperation.Link; + + if (message.DragEventArgs.DragUIOverride is not null) + { + message.DragEventArgs.DragUIOverride.IsContentVisible = true; + message.DragEventArgs.DragUIOverride.IsGlyphVisible = false; + message.DragEventArgs.DragUIOverride.IsCaptionVisible = false; + } + + return Task.CompletedTask; + } + } +} diff --git a/TheXamlGuy.TaskbarGroup.Flyout/Views/TaskbarButtonGroupView.xaml b/TheXamlGuy.TaskbarGroup.Flyout/Views/TaskbarButtonGroupView.xaml index dfb354a..370f5f5 100644 --- a/TheXamlGuy.TaskbarGroup.Flyout/Views/TaskbarButtonGroupView.xaml +++ b/TheXamlGuy.TaskbarGroup.Flyout/Views/TaskbarButtonGroupView.xaml @@ -8,7 +8,7 @@ - + () .AddTransient() .AddTransient() + .AddAsyncHandler() .AddAsyncHandler() .AddTransient(); } diff --git a/TheXamlGuy.TaskbarGroup/LifeCycles/ApplicationHost.cs b/TheXamlGuy.TaskbarGroup/LifeCycles/ApplicationHost.cs index 2543693..debc22a 100644 --- a/TheXamlGuy.TaskbarGroup/LifeCycles/ApplicationHost.cs +++ b/TheXamlGuy.TaskbarGroup/LifeCycles/ApplicationHost.cs @@ -2,21 +2,29 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using System.Windows; using TheXamlGuy.TaskbarGroup.Core; namespace TheXamlGuy.TaskbarGroup { public sealed class ApplicationHost : IHostedService { - private readonly IEnumerable initializables; - private bool isInitialized; private readonly TaskbarButtonFlyoutWindow flyoutWindow; + private readonly IEnumerable initializables; + private readonly IMediator mediator; + private bool isInitialized; public ApplicationHost(IEnumerable initializables, + IMessenger messenger, + IMediator mediator, TaskbarButtonFlyoutWindow flyoutWindow) { this.initializables = initializables; + this.mediator = mediator; this.flyoutWindow = flyoutWindow; + + messenger.Subscribe(OnTaskbarButtonInvoked); + messenger.Subscribe(OnTaskbarButtonDragEnter); } public async Task StartAsync(CancellationToken cancellationToken) @@ -27,11 +35,11 @@ namespace TheXamlGuy.TaskbarGroup isInitialized = true; } + public async Task StopAsync(CancellationToken cancellationToken) { await Task.CompletedTask; } - private async Task InitializeAsync() { if (!isInitialized) @@ -45,12 +53,26 @@ namespace TheXamlGuy.TaskbarGroup } } + private void OnTaskbarButtonDragEnter(TaskbarButtonDragEnter args) + { + Application.Current.Dispatcher.Invoke(() => Open(args.Button)); + } + + private void OnTaskbarButtonInvoked(TaskbarButtonInvoked args) + { + Application.Current.Dispatcher.Invoke(() => Open(args.Button)); + } + + private void Open(TaskbarButton button) + { + mediator.Handle(new TaskbarButtonFlyoutActivation(button)); + } + private async Task StartupAsync() { if (!isInitialized) { flyoutWindow.Show(); - await Task.CompletedTask; } } diff --git a/TheXamlGuy.TaskbarGroup/LifeCycles/TaskbarButtonFlyoutActivationHandler.cs b/TheXamlGuy.TaskbarGroup/LifeCycles/TaskbarButtonFlyoutActivationHandler.cs index 7f3b4c5..2fb5778 100644 --- a/TheXamlGuy.TaskbarGroup/LifeCycles/TaskbarButtonFlyoutActivationHandler.cs +++ b/TheXamlGuy.TaskbarGroup/LifeCycles/TaskbarButtonFlyoutActivationHandler.cs @@ -64,6 +64,7 @@ namespace TheXamlGuy.TaskbarGroup flyout.ShowAt(placement); } + window.Show(); window.Activate(); } } diff --git a/TheXamlGuy.TaskbarGroup/Windows/TaskbarButtonFlyoutWindow.cs b/TheXamlGuy.TaskbarGroup/Windows/TaskbarButtonFlyoutWindow.cs index f79de11..ab259af 100644 --- a/TheXamlGuy.TaskbarGroup/Windows/TaskbarButtonFlyoutWindow.cs +++ b/TheXamlGuy.TaskbarGroup/Windows/TaskbarButtonFlyoutWindow.cs @@ -2,29 +2,24 @@ using System.Windows; using System.Windows.Media; using System.Windows.Threading; -using TheXamlGuy.TaskbarGroup.Core; using TheXamlGuy.TaskbarGroup.Flyout.Controls; namespace TheXamlGuy.TaskbarGroup { public class TaskbarButtonFlyoutWindow : TransparentXamlWindow { - private readonly IMediator mediator; - private bool isDpiChanging; - public TaskbarButtonFlyoutWindow(IMessenger messenger, - IMediator mediator) + public TaskbarButtonFlyoutWindow() { - this.mediator = mediator; - - DpiChanged += OnDpiChanged; Deactivated += OnDeactivated; Topmost = true; Width = 258; Height = 258; - messenger.Subscribe(OnTaskbarButtonInvoked); - messenger.Subscribe(OnTaskbarButtonDragEnter); + Dispatcher.BeginInvoke(new Action(() => + { + Hide(); + }), DispatcherPriority.ContextIdle, null); } private void OnDeactivated(object? sender, EventArgs args) @@ -32,49 +27,8 @@ namespace TheXamlGuy.TaskbarGroup if (XamlContent is TaskbarButtonFlyout flyout) { flyout.Close(); + Hide(); } } - - private async void OnDpiChanged(object sender, DpiChangedEventArgs args) - { - if (isDpiChanging) return; - - isDpiChanging = true; - - await Dispatcher.Invoke(async () => - { - Visibility = Visibility.Visible; - await Dispatcher.BeginInvoke(new Action(() => - { - VisualTreeHelper.SetRootDpi(this, args.OldDpi); - }), DispatcherPriority.ContextIdle, null); - - await Dispatcher.BeginInvoke(new Action(() => - { - VisualTreeHelper.SetRootDpi(this, args.NewDpi); - }), DispatcherPriority.ContextIdle, null); - - await Dispatcher.BeginInvoke(new Action(() => - { - Visibility = Visibility.Hidden; - isDpiChanging = false; - }), DispatcherPriority.ContextIdle, null); - }); - } - - private void OnTaskbarButtonDragEnter(TaskbarButtonDragEnter args) - { - Dispatcher.Invoke(() => Open(args.Button)); - } - - private void OnTaskbarButtonInvoked(TaskbarButtonInvoked args) - { - Dispatcher.Invoke(() => Open(args.Button)); - } - - private void Open(TaskbarButton button) - { - mediator.Handle(new TaskbarButtonFlyoutActivation(button)); - } } } diff --git a/TheXamlGuy.TaskbarGroup/Windows/XamlWindow.cs b/TheXamlGuy.TaskbarGroup/Windows/XamlWindow.cs index 19ab128..d5452e0 100644 --- a/TheXamlGuy.TaskbarGroup/Windows/XamlWindow.cs +++ b/TheXamlGuy.TaskbarGroup/Windows/XamlWindow.cs @@ -1,15 +1,20 @@ using Microsoft.Toolkit.Wpf.UI.XamlHost; +using System; using System.Windows; +using System.Windows.Media; +using System.Windows.Threading; namespace TheXamlGuy.TaskbarGroup { public class XamlWindow : Window where TXamlContent : Windows.UI.Xaml.UIElement { + private bool isDpiChanging; private WindowsXamlHost? xamlHost; public XamlWindow() { Initialize(); + DpiChanged += OnDpiChanged; } public TXamlContent? XamlContent @@ -37,5 +42,32 @@ namespace TheXamlGuy.TaskbarGroup Content = xamlHost; } + + private async void OnDpiChanged(object sender, DpiChangedEventArgs args) + { + if (isDpiChanging) return; + + isDpiChanging = true; + + await Dispatcher.Invoke(async () => + { + Visibility = Visibility.Visible; + await Dispatcher.BeginInvoke(new Action(() => + { + VisualTreeHelper.SetRootDpi(this, args.OldDpi); + }), DispatcherPriority.ContextIdle, null); + + await Dispatcher.BeginInvoke(new Action(() => + { + VisualTreeHelper.SetRootDpi(this, args.NewDpi); + }), DispatcherPriority.ContextIdle, null); + + await Dispatcher.BeginInvoke(new Action(() => + { + Visibility = Visibility.Hidden; + isDpiChanging = false; + }), DispatcherPriority.ContextIdle, null); + }); + } } }