mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-23 19:49:43 +01:00
The menu does show up, it's just totally in the wrong spot
This commit is contained in:
@@ -476,6 +476,7 @@ public partial class ShellViewModel : ObservableObject,
|
||||
navigationToken,
|
||||
TaskContinuationOptions.None,
|
||||
_scheduler);
|
||||
return;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
@@ -178,6 +178,12 @@ public sealed partial class DockControl : UserControl, IRecipient<CloseContextMe
|
||||
borderPos.X + (dockItem.ActualWidth / 2),
|
||||
borderPos.Y + (dockItem.ActualHeight / 2));
|
||||
|
||||
// // borderCenter is in DIPs, relative to the dock window.
|
||||
// // we need screen DIPs
|
||||
// var windowPos = dockItem.XamlRoot.Content.XamlRoot.TransformToVisual(null).TransformPoint(new Point(0, 0));
|
||||
// var screenPos = new Point(
|
||||
// borderCenter.X + windowPos.X,
|
||||
// borderCenter.Y + windowPos.Y);
|
||||
InvokeItem(item, borderCenter);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,30 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
|
||||
<Grid.Resources>
|
||||
<Style
|
||||
x:Name="ContextMenuFlyoutStyle"
|
||||
BasedOn="{StaticResource DefaultFlyoutPresenterStyle}"
|
||||
TargetType="FlyoutPresenter">
|
||||
<Style.Setters>
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Background" Value="{ThemeResource DesktopAcrylicTransparentBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
|
||||
<!-- Backdrop requires ShouldConstrainToRootBounds="False" -->
|
||||
<Flyout
|
||||
x:Name="ContextMenuFlyout"
|
||||
FlyoutPresenterStyle="{StaticResource ContextMenuFlyoutStyle}"
|
||||
Opened="ContextMenuFlyout_Opened"
|
||||
ShouldConstrainToRootBounds="False"
|
||||
SystemBackdrop="{ThemeResource AcrylicBackgroundFillColorDefaultBackdrop}">
|
||||
<cpcontrols:ContextMenu x:Name="ContextMenuControl" MaxHeight="512" />
|
||||
</Flyout>
|
||||
</Grid.Resources>
|
||||
|
||||
<!-- Colorization overlay for transparent backdrop -->
|
||||
<Border
|
||||
x:Name="ColorizationOverlay"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CmdPal.UI.ViewModels;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Dock;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Messages;
|
||||
@@ -16,6 +17,7 @@ using Microsoft.UI.Composition.SystemBackdrops;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Windows.Foundation;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
@@ -35,6 +37,8 @@ public sealed partial class DockWindow : WindowEx,
|
||||
IRecipient<BringToTopMessage>,
|
||||
IRecipient<RequestShowPaletteAtMessage>,
|
||||
IRecipient<QuitMessage>,
|
||||
IRecipient<ShowCommandInContextMenuMessage>,
|
||||
IRecipient<CloseContextMenuMessage>,
|
||||
IDisposable
|
||||
{
|
||||
#pragma warning disable SA1306 // Field names should begin with lower-case letter
|
||||
@@ -93,6 +97,9 @@ public sealed partial class DockWindow : WindowEx,
|
||||
WeakReferenceMessenger.Default.Register<RequestShowPaletteAtMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<QuitMessage>(this);
|
||||
|
||||
WeakReferenceMessenger.Default.Register<ShowCommandInContextMenuMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<CloseContextMenuMessage>(this);
|
||||
|
||||
_hwnd = GetWindowHandle(this);
|
||||
|
||||
// Subclass the window to intercept messages
|
||||
@@ -529,6 +536,11 @@ public sealed partial class DockWindow : WindowEx,
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ContextMenuFlyout_Opened(object sender, object e)
|
||||
{
|
||||
ContextMenuControl.FocusSearchBox();
|
||||
}
|
||||
|
||||
public void Receive(QuitMessage message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
@@ -539,6 +551,25 @@ public sealed partial class DockWindow : WindowEx,
|
||||
});
|
||||
}
|
||||
|
||||
public void Receive(ShowCommandInContextMenuMessage message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
ShowFlyoutOnUiThread(message.Context, message.Position);
|
||||
});
|
||||
}
|
||||
|
||||
public void Receive(CloseContextMenuMessage message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
if (ContextMenuFlyout.IsOpen)
|
||||
{
|
||||
ContextMenuFlyout.Hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void IRecipient<RequestShowPaletteAtMessage>.Receive(RequestShowPaletteAtMessage message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => RequestShowPaletteOnUiThread(message.PosDips));
|
||||
@@ -546,6 +577,10 @@ public sealed partial class DockWindow : WindowEx,
|
||||
|
||||
private void RequestShowPaletteOnUiThread(Point posDips)
|
||||
{
|
||||
// TODO!!!! posDips was originally relative to the dock window.
|
||||
// It's now relative to the screen.
|
||||
// this method wasn't yet updated for that.
|
||||
|
||||
// pos is relative to our root. We need to convert to screen coords.
|
||||
var rootPosDips = Root.TransformToVisual(null).TransformPoint(new Point(0, 0));
|
||||
var screenPosDips = new Point(rootPosDips.X + posDips.X, rootPosDips.Y + posDips.Y);
|
||||
@@ -613,6 +648,93 @@ public sealed partial class DockWindow : WindowEx,
|
||||
WeakReferenceMessenger.Default.Send<ShowPaletteAtMessage>(new(screenPosPixels, anchorPoint));
|
||||
}
|
||||
|
||||
private void ShowFlyoutOnUiThread(IContextMenuContext context, Point position)
|
||||
{
|
||||
ContextMenuControl.ViewModel.SelectedItem = context;
|
||||
|
||||
// Depending on the side we're on, change the direction of the results
|
||||
switch (_settings.Side)
|
||||
{
|
||||
case DockSide.Top:
|
||||
case DockSide.Left:
|
||||
case DockSide.Right:
|
||||
ContextMenuControl.ViewModel.FilterOnTop = true;
|
||||
break;
|
||||
case DockSide.Bottom:
|
||||
ContextMenuControl.ViewModel.FilterOnTop = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// position is relative to our root. We need to convert to screen coords.
|
||||
//
|
||||
// Root.TransformToVisual(null) will always return 0,0, because Root is at the root of our window.
|
||||
//
|
||||
// we instead need:
|
||||
|
||||
// var rootPosDips = Root.TransformToVisual(null).TransformPoint(new Point(0, 0));
|
||||
|
||||
// var screenPosDips = new Point(rootPosDips.X + position.X, rootPosDips.Y + position.Y);
|
||||
|
||||
// TODO! deal with DPI - I'm sure this is wrong
|
||||
var dpi = PInvoke.GetDpiForWindow(_hwnd);
|
||||
PInvoke.GetWindowRect(_hwnd, out var ourRect);
|
||||
var scaleFactor = dpi / 96.0;
|
||||
|
||||
var positionPixels = new Point(position.X * scaleFactor, position.Y * scaleFactor);
|
||||
|
||||
var screenPosPixels = // new Point(screenPosDips.X * scaleFactor, screenPosDips.Y * scaleFactor);
|
||||
new Point(ourRect.left + positionPixels.X, ourRect.top + positionPixels.Y);
|
||||
|
||||
var screenWidth = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXSCREEN);
|
||||
var screenHeight = PInvoke.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYSCREEN);
|
||||
var onTopHalf = screenPosPixels.Y < screenHeight / 2;
|
||||
var onLeftHalf = screenPosPixels.X < screenWidth / 2;
|
||||
var onRightHalf = !onLeftHalf;
|
||||
var onBottomHalf = !onTopHalf;
|
||||
var anchorPoint = _settings.Side switch
|
||||
{
|
||||
DockSide.Top => onLeftHalf ? AnchorPoint.TopLeft : AnchorPoint.TopRight,
|
||||
DockSide.Bottom => onLeftHalf ? AnchorPoint.BottomLeft : AnchorPoint.BottomRight,
|
||||
DockSide.Left => onTopHalf ? AnchorPoint.TopLeft : AnchorPoint.BottomLeft,
|
||||
DockSide.Right => onTopHalf ? AnchorPoint.TopRight : AnchorPoint.BottomRight,
|
||||
_ => AnchorPoint.TopLeft,
|
||||
};
|
||||
|
||||
// we also need to slide the anchor point a bit away from the dock
|
||||
var paddingDips = 8;
|
||||
var paddingPixels = paddingDips * scaleFactor;
|
||||
|
||||
// Depending on the side we're on, we need to offset differently
|
||||
switch (_settings.Side)
|
||||
{
|
||||
case DockSide.Top:
|
||||
screenPosPixels.Y += paddingPixels;
|
||||
break;
|
||||
case DockSide.Bottom:
|
||||
screenPosPixels.Y -= paddingPixels;
|
||||
break;
|
||||
case DockSide.Left:
|
||||
screenPosPixels.X += paddingPixels;
|
||||
break;
|
||||
case DockSide.Right:
|
||||
screenPosPixels.X -= paddingPixels;
|
||||
break;
|
||||
}
|
||||
|
||||
// var finalPosDips = new Point((screenPosPixels.X / scaleFactor) - rootPosDips.X, (screenPosPixels.Y / scaleFactor) - rootPosDips.Y);
|
||||
var finalPosDips = new Point(
|
||||
(screenPosPixels.X - ourRect.left) / scaleFactor,
|
||||
(screenPosPixels.Y - ourRect.top) / scaleFactor);
|
||||
|
||||
ContextMenuFlyout.ShowAt(
|
||||
Root,
|
||||
new FlyoutShowOptions()
|
||||
{
|
||||
ShowMode = FlyoutShowMode.Standard,
|
||||
Position = finalPosDips,
|
||||
});
|
||||
}
|
||||
|
||||
public DockWindowViewModel WindowViewModel => _windowViewModel;
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -16,29 +16,6 @@
|
||||
Closed="MainWindow_Closed"
|
||||
mc:Ignorable="d">
|
||||
<Grid x:Name="RootElement">
|
||||
<Grid.Resources>
|
||||
<Style
|
||||
x:Name="ContextMenuFlyoutStyle"
|
||||
BasedOn="{StaticResource DefaultFlyoutPresenterStyle}"
|
||||
TargetType="FlyoutPresenter">
|
||||
<Style.Setters>
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Background" Value="{ThemeResource DesktopAcrylicTransparentBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
|
||||
<!-- Backdrop requires ShouldConstrainToRootBounds="False" -->
|
||||
<Flyout
|
||||
x:Name="ContextMenuFlyout"
|
||||
FlyoutPresenterStyle="{StaticResource ContextMenuFlyoutStyle}"
|
||||
Opened="ContextMenuFlyout_Opened"
|
||||
ShouldConstrainToRootBounds="False"
|
||||
SystemBackdrop="{ThemeResource AcrylicBackgroundFillColorDefaultBackdrop}">
|
||||
<controls:ContextMenu x:Name="ContextMenuControl" />
|
||||
</Flyout>
|
||||
</Grid.Resources>
|
||||
|
||||
<controls:BlurImageControl
|
||||
HorizontalAlignment="Stretch"
|
||||
|
||||
@@ -28,7 +28,6 @@ using Microsoft.UI.Composition.SystemBackdrops;
|
||||
using Microsoft.UI.Input;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.Foundation;
|
||||
@@ -58,8 +57,6 @@ public sealed partial class MainWindow : WindowEx,
|
||||
IRecipient<NavigationDepthMessage>,
|
||||
IRecipient<SearchQueryMessage>,
|
||||
IRecipient<ErrorOccurredMessage>,
|
||||
IRecipient<ShowCommandInContextMenuMessage>,
|
||||
IRecipient<CloseContextMenuMessage>,
|
||||
IRecipient<DragStartedMessage>,
|
||||
IRecipient<DragCompletedMessage>,
|
||||
IDisposable
|
||||
@@ -144,8 +141,6 @@ public sealed partial class MainWindow : WindowEx,
|
||||
WeakReferenceMessenger.Default.Register<NavigationDepthMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<SearchQueryMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<ErrorOccurredMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<ShowCommandInContextMenuMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<CloseContextMenuMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<DragStartedMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<DragCompletedMessage>(this);
|
||||
|
||||
@@ -680,41 +675,6 @@ public sealed partial class MainWindow : WindowEx,
|
||||
_sessionErrorCount++;
|
||||
}
|
||||
|
||||
public void Receive(ShowCommandInContextMenuMessage message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
ContextMenuControl.ViewModel.SelectedItem = message.Context;
|
||||
ContextMenuFlyout.ShouldConstrainToRootBounds = false;
|
||||
ContextMenuFlyout.ShowMode = FlyoutShowMode.Standard;
|
||||
ContextMenuFlyout.ShowAt(RootElement);
|
||||
|
||||
// ContextMenuFlyout.ShowAt(
|
||||
// RootElement,
|
||||
// new FlyoutShowOptions()
|
||||
// {
|
||||
// ShowMode = FlyoutShowMode.Standard,
|
||||
// Position = message.Position,
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
public void Receive(CloseContextMenuMessage message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
if (ContextMenuFlyout.IsOpen)
|
||||
{
|
||||
ContextMenuFlyout.Hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void ContextMenuFlyout_Opened(object sender, object e)
|
||||
{
|
||||
ContextMenuControl.FocusSearchBox();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ends the current telemetry session and emits the CmdPal_SessionDuration event.
|
||||
/// Aggregates all session metrics collected since ShowWindow and sends them to telemetry.
|
||||
@@ -1251,6 +1211,27 @@ public sealed partial class MainWindow : WindowEx,
|
||||
});
|
||||
}
|
||||
|
||||
// public void Receive(ShowCommandInContextMenuMessage message)
|
||||
// {
|
||||
// DispatcherQueue.TryEnqueue(() =>
|
||||
// {
|
||||
// ContextMenuControl.ViewModel.SelectedItem = message.Context;
|
||||
// ContextMenuFlyout.ShouldConstrainToRootBounds = false;
|
||||
// ContextMenuFlyout.ShowMode = FlyoutShowMode.Standard;
|
||||
|
||||
// // message.Position is in dips,
|
||||
|
||||
// ContextMenuFlyout.ShowAt(RootElement);
|
||||
|
||||
// // ContextMenuFlyout.ShowAt(
|
||||
// // RootElement,
|
||||
// // new FlyoutShowOptions()
|
||||
// // {
|
||||
// // ShowMode = FlyoutShowMode.Standard,
|
||||
// // Position = message.Position,
|
||||
// // });
|
||||
// });
|
||||
// }
|
||||
private unsafe void StealForeground()
|
||||
{
|
||||
var foregroundWindow = PInvoke.GetForegroundWindow();
|
||||
|
||||
Reference in New Issue
Block a user